// *****************************************************************************
// *****************************************************************************
// Copyright 2012 - 2017, Cadence Design Systems
//
// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source
// Distribution,  Product Version 5.8.
//
// Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
//    implied. See the License for the specific language governing
//    permissions and limitations under the License.
//
// For updates, support, or to become part of the LEF/DEF Community,
// check www.openeda.org for details.
// *****************************************************************************
// *****************************************************************************

// This file contains code for implementing the lefwriter 5.3
// It has all the functions user can call in their callbacks or
// just their writer to write out the correct lef syntax.
//
// Author: Wanda da Rosa
// Date:   Summer, 1998
//
// Revisions:

#include "lefwWriter.hpp"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#include "crypt.hpp"
#include "lefiKRDefs.hpp"

BEGIN_LEF_PARSER_NAMESPACE

// States of the writer.
#define LEFW_UNINIT 0
#define LEFW_INIT 1
#define LEFW_ARRAY_START 2
#define LEFW_BEGINEXT_START 3
#define LEFW_CORRECTTABLE_START 4
#define LEFW_IRDROP_START 5
#define LEFW_LAYER_START 6
#define LEFW_LAYERROUTING_START 7
#define LEFW_LAYERROUTING_SP_START 8
#define LEFW_MACRO_START 9
#define LEFW_NOISETABLE_START 10
#define LEFW_NONDEFAULTRULE_START 11
#define LEFW_PROPERTYDEF_START 12
#define LEFW_SPACING_START 13
#define LEFW_UNITS_START 14
#define LEFW_VIA_START 15
#define LEFW_VIARULE_START 16
#define LEFW_VIARULEGEN_START 17

#define LEFW_ANTENNASIZE 18
#define LEFW_ARRAY 19
#define LEFW_BEGINEXT 20
#define LEFW_BUSBITCHARS 21
#define LEFW_CASESENSITIVE 22
#define LEFW_CORRECTTABLE 23
#define LEFW_DIELECTRIC 24
#define LEFW_DIVIDERCHAR 25
#define LEFW_EDGERATE 26
#define LEFW_IRDROP 27
#define LEFW_LAYER 28
#define LEFW_LAYERACCURRENT 29
#define LEFW_LAYERDCCURRENT 30
#define LEFW_LAYERROUTING 31
#define LEFW_LAYERROUTINGWIDTH 32
#define LEFW_MACRO 33
#define LEFW_MACRO_CAPACITANCE 34
#define LEFW_MACRO_INPUTNOISEMARGIN 35
#define LEFW_MACRO_FALLCURRENTSOURCE 36
#define LEFW_MACRO_FALLSATCUR 37
#define LEFW_MACRO_FALLTHRESH 38
#define LEFW_MACRO_FALLVOLTAGETHRESHOLD 39
#define LEFW_MACRO_IV_TABLES 40
#define LEFW_MACRO_LEAKAGE 41
#define LEFW_MACRO_LEQ 42
#define LEFW_MACRO_OUTPUTNOISEMARGIN 43
#define LEFW_MACRO_OUTPUTRESISTANCE 44
#define LEFW_MACRO_PINFOREIGN 45
#define LEFW_MACRO_PINLEQ 46
#define LEFW_MACRO_POWER 47
#define LEFW_MACRO_PULLDOWNRES 48
#define LEFW_MACRO_RESISTANCE 49
#define LEFW_MACRO_RISESATCUR 50
#define LEFW_MACRO_RISETHRESH 51
#define LEFW_MACRO_RISEVOLTAGETHRESHOLD 52
#define LEFW_MACRO_SOURCE 53
#define LEFW_MACRO_TIEOFFR 54
#define LEFW_MACRO_TIMING 55
#define LEFW_MACRO_VHI 56
#define LEFW_MACRO_VLO 57
#define LEFW_MINFEATURE 58
#define LEFW_NONDEFAULTRULE 59
#define LEFW_NONDEFAULTRULELAYER 60
#define LEFW_NOISEMARGIN 61
#define LEFW_NOISETABLE 62
#define LEFW_NOWIREEXTATPIN 63
#define LEFW_PROPERTYDEF 64
#define LEFW_SCALEFACTOR 65
#define LEFW_SITE 66
#define LEFW_SPACING 67
#define LEFW_THRESHOLD1 68
#define LEFW_THRESHOLD2 69
#define LEFW_UNITS 70
#define LEFW_VERSION 71
#define LEFW_VIA 72
#define LEFW_VIAFOREIGN 73
#define LEFW_VIARULE 74
#define LEFW_VIARULEGENERATE 75
#define LEFW_VIARULEGEN 76
#define LEFW_VIATOPOFSTACKONLY 77
#define LEFW_VIAVIARULE 78

#define LEFW_END 79
#define LEFW_ARRAY_END 80
#define LEFW_BEGINEXT_END 81
#define LEFW_CORRECTTABLE_END 82
#define LEFW_IRDROP_END 83
#define LEFW_LAYER_END 84
#define LEFW_LAYERROUTING_END 85
#define LEFW_LAYERROUTING_SPACINGTABLE_END 86
#define LEFW_MACRO_END 87
#define LEFW_NOISETABLE_END 88
#define LEFW_NONDEFAULTRULE_END 89
#define LEFW_PROPERTYDEF_END 90
#define LEFW_SITE_END 91
#define LEFW_SPACING_END 92
#define LEFW_VIA_END 93
#define LEFW_VIARULE_END 94
#define LEFW_VIARULEGEN_END 95
#define LEFW_UNITS_END 96

// 5.4
// ANTENNA for LAYER
#define LEFW_ANTENNAINPUTGATEAREA 97
#define LEFW_ANTENNAINOUTDIFFAREA 98
#define LEFW_ANTENNAOUTPUTDIFFAREA 99
#define LEFW_ANTENNAMODEL 100
#define LEFW_ANTENNAAREARATIO 101
#define LEFW_ANTENNADIFFAREARATIO 102
#define LEFW_ANTENNADIFFAREARATIOPWL 103
#define LEFW_ANTENNACUMAREARATIO 104
#define LEFW_ANTENNACUMDIFFAREARATIO 105
#define LEFW_ANTENNACUMDIFFAREARATIOPWL 106
#define LEFW_ANTENNAAREAFACTOR 107
#define LEFW_ANTENNASIDEAREARATIO 108
#define LEFW_ANTENNADIFFSIDEAREARATIO 109
#define LEFW_ANTENNADIFFSIDEAREARATIOPWL 110
#define LEFW_ANTENNACUMSIDEAREARATIO 111
#define LEFW_ANTENNACUMDIFFSIDEAREARATIO 112
#define LEFW_ANTENNACUMDIFFSIDEAREARATIOPWL 113
#define LEFW_ANTENNASIDEAREAFACTOR 114
// ANTENNA for MACRO PIN
#define LEFW_ANTENNAPARTIALMETALAREA 115
#define LEFW_ANTENNAPARTIALMETALSIDEAREA 116
#define LEFW_ANTENNAGATEAREA 117
#define LEFW_ANTENNADIFFAREA 118
#define LEFW_ANTENNAMAXAREACAR 119
#define LEFW_ANTENNAMAXSIDEAREACAR 120
#define LEFW_ANTENNAPARTIALCUTAREA 121
#define LEFW_ANTENNAMAXCUTCAR 122
#define LEFW_CLEARANCEMEASURE 123
#define LEFW_DENSITYCHECKWINDOW 124
#define LEFW_DENSITYCHECKSTEP 125
#define LEFW_DESIGNRULEWIDTH 126
#define LEFW_FILLACTIVESPACING 127
#define LEFW_MANUFACTURINGGRID 128
#define LEFW_MAXADJACENTSLOTSPACING 129
#define LEFW_MAXCOAXIALSLOTSPACING 130
#define LEFW_MAXEDGESLOTSPACING 131
#define LEFW_MAXIMUMDENSITY 132
#define LEFW_MINIMUMDENSITY 133
#define LEFW_ROWABUTSPACING 134
#define LEFW_ROWMINSPACING 135
#define LEFW_SLOTWIREWIDTH 136
#define LEFW_SLOTWIRELENGTH 137
#define LEFW_SLOTWIDTH 138
#define LEFW_SLOTLENGTH 139
#define LEFW_SPLITWIREWIDTH 140
#define LEFW_USEMINSPACING 141
#define LEFW_FIXEDMASK 142

#define LEFW_DONE 999

#define MAXSYN 143

// *****************************************************************************
// Global Variables
// *****************************************************************************
using LEFI_LOG_FUNCTION = void (*)(const char*);
using LEFI_WARNING_LOG_FUNCTION = void (*)(const char*);

LEFI_LOG_FUNCTION lefwErrorLogFunction;
LEFI_WARNING_LOG_FUNCTION lefwWarningLogFunction;

FILE* lefwFile = nullptr;         // File to write to.
int lefwSynArray[MAXSYN];         // array of syntax
int lefwLines = 0;                // number of lines written
int lefwState = LEFW_UNINIT;      // Current state of writer
int lefwDidInit = 0;              // required section
int lefwDidLayer = 0;             // required section
int lefwDidVia = 0;               // required section
int lefwDidViaRule = 0;           // required section
int lefwDidViaSite = 0;           // required section
int lefwDidViaMacro = 0;          // required section
int lefwCounter = 0;              // number of nets, components in section
int lefwLineItemCounter = 0;      // number of items on current line
int lefwHasArrayReq = 0;          // array required data
int lefwIsArrayFloorp = 0;        // array floorplan flag
int lefwIsArrayDef = 0;           // array default cap flag
int lefwIsCorrectTable = 0;       // correctiontable flag
int lefwIsCut = 0;                // cut layer
int lefwIsEdgerate = 0;           // edgerate within noisetable
int lefwIsFloorp = 0;             // floorplan within array
int lefwIsImplant = 0;            // implant layer
int lefwIsMacroDensity = 0;       // macro density flag
int lefwIsMacroObs = 0;           // macro obs flag
int lefwIsMacroObsLayer = 0;      // macro obs layer within macro obs
int lefwIsMacroPin = 0;           // macro pin flag
int lefwIsMacroPinPortLayer = 0;  // macro pin port layer within macro pin port
int lefwIsMacroPinPort = 0;       // macro pin port within macro pin
int lefwIsMacroTiming = 0;        // macro timing flag
int lefwIsMacroTimingModel = 0;   // macro timing model flag
int lefwIsMaxviastack = 0;        // maximum stacked-via
int lefwIsNoiseTable = 0;         // noisetable flag
int lefwIsNonDefaultRule = 0;     // nondefaultrule flag
int lefwIsOutResist = 0;          // outputResistance within edgerate
int lefwIsRouting = 0;            // routing
int lefwIsRoutingMinCut = 0;      // routing Minimumcut
int lefwIsRoutingMinCutDist = 0;  // routing Minimumcut distance
int lefwIsRoutingMinCutLen = 0;   // routing Minimumcut length within
int lefwIsRoutingReqData = 0;     // layer routing required data are provided
int lefwNumViaRuleLayers = 0;     // number of via rule in a via rule
int lefwOldState = 0;             // the previous state
int lefwTableLen = 0;             // width or cutarea for the tableEntries
int lefwHasInit = 0;              // for lefwInit has called
int lefwHasInitCbk = 0;           // for lefwInitCbk has called
static int lefwWriteEncrypt
    = 0;                      // for writing out encrypted file, default is 0
static int prtSemiColon = 0;  // sometimes ; is not printed yet
static int prtNewLine = 0;    // sometimes need to print a new line
static int lefwHasLayerRoutingRange = 0;    // mark if layer routing has range
static int lefwHasLayerRoutingSpacing = 0;  // layer routing is lengththreshold
static int lefwHasLayerRoutingEol = 0;  // mark if layer routing is endofline
static int lefwIsLayerCutSpacing = 0;   // mark if layer cut spacing
static int lefwAMaxAreaCar = 0;         // only allow to define once per pin
static int lefwAMaxSideAreaCar = 0;     // only allow to define once per pin
static int lefwAMaxCutCar = 0;          // only allow to define once per pin
static int lefwSpacingVal = 0;          // either this or lefwWidthVal
static int lefwWidthVal = 0;            // is allowed
static double versionNum = 5.7;         // default to 5.7
static int lefwAntenna54 = 0;           // to keep track 5.4 antenna is used
static int lefwAntenna53 = 0;           // to keep track 5.3 antenna is used
static int lefwObsoleteNum = -1;  // keep track the obsolote syntax for error
static int lefw54Num = -1;        // keep track the 5.4 syntax for error
static int lefwViaHasVal = 0;  // keep track only ViaRule or Resistance in a via

char lefwStateStr[MAXSYN][80] = {
    "UNITS",                                          //  0
    "INIT",                                           //  1
    "ARRAY",                                          //  2
    "BEGINEXT",                                       //  3
    "CORRECTTABLE",                                   //  4
    "IRDROP",                                         //  5
    "LAYER",                                          //  6
    "LAYERROUTING",                                   //  7
    "LAYERROUTINGSPACINGTABLE",                       //  8
    "MACRO",                                          //  9
    "NOISETABLE",                                     // 10
    "NONDEFAULTRULE",                                 // 11
    "PROPERTYDEFINITION",                             // 12
    "SPACING",                                        // 13
    "UNITS",                                          // 14
    "VIA",                                            // 15
    "VIARULE",                                        // 16
    "VIARULEGEN",                                     // 17
    "ANTENNASIZE",                                    // 18
    "ARRAY",                                          // 19
    "BEGINEXT",                                       // 20
    "BUSBITCHARS",                                    // 21
    "CASESENSITIVE",                                  // 22
    "CORRECTABLE",                                    // 23
    "DIELECTRIC",                                     // 24
    "DIVIDERCHAR",                                    // 25
    "EDGERATE",                                       // 26
    "IRDROP",                                         // 27
    "LAYER",                                          // 28
    "LAYERACCURRENT",                                 // 29
    "LAYERDCCURRENT",                                 // 30
    "LAYERROUTING",                                   // 31
    "LAYERROUTINGWIDTH",                              // 32
    "MACRO",                                          // 33
    "MACRO_CAPACITANCE",                              // 34
    "MACRO_INPUTNOISEMARGIN",                         // 35
    "MACRO_FALLCURRENTSOURCE",                        // 36
    "MACRO_FALLSATCUR",                               // 37
    "MACRO_FALLTHRESH",                               // 38
    "MACRO_FALLVOLTAGETHRESHOLD",                     // 39
    "MACRO_IV_TABLES",                                // 40
    "MACRO_LEAKAGE",                                  // 41
    "MACRO_LEQ",                                      // 42
    "MACRO_OUTPUTNOISEMARGIN",                        // 43
    "MACRO_OUTPUTRESISTANCE",                         // 44
    "MACRO_PINFOREIGN",                               // 45
    "MACRO_PINLEQ",                                   // 46
    "MACRO_POWER",                                    // 47
    "MACRO_PULLDOWNRES",                              // 48
    "MACRO_RESISTANCE",                               // 49
    "MACRO_RISESATCUR",                               // 50
    "MACRO_RISETHRESH",                               // 51
    "MACRO_RISEVOLTAGETHRESHOLD",                     // 52
    "MACRO_SOURCE",                                   // 53
    "MACRO_TIEOFFR",                                  // 54
    "MACRO_TIMING",                                   // 55
    "MACRO_VHI",                                      // 56
    "MACRO_VLO",                                      // 57
    "MINFEATURE",                                     // 58
    "NONDEFAULTRULE",                                 // 59
    "NONDEFAULTRULELAYERRESIST_CAPACITANCE_EDGECAP",  // 60
    "NOISEMARGIN",                                    // 61
    "NOISETABLE",                                     // 62
    "NOWIREEXTSIONATPIN",                             // 63
    "PROPERTYDEFINITION",                             // 64
    "EDGERATESCALEFACTOR",                            // 65
    "SITE",                                           // 66
    "SPACING",                                        // 67
    "EDGERATETHRESHOLD1",                             // 68
    "EDGERATETHRESHOLD2",                             // 69
    "UNTIS",                                          // 70
    "VERSION",                                        // 71
    "VIA",                                            // 72
    "VIAFOREIGN",                                     // 73
    "VIARULE",                                        // 74
    "VIARULEDIRECTION_OVERHANG_METALOVERHANG",        // 75
    "VIARULEGEN",                                     // 76
    "VIATOPOFSTACKONLY",                              // 77
    "VIAVIARULE",                                     // 78
    "END",                                            // 79
    "ARRAY",                                          // 80
    "BEGINEXT",                                       // 81
    "CORRECTABLE",                                    // 82
    "IRDROP",                                         // 83
    "LAYER",                                          // 84
    "LAYERROUTING",                                   // 85
    "LAYERROUTINGSPACINGTABLE",                       // 86
    "MACRO",                                          // 87
    "NOISETABLE",                                     // 88
    "NONDEFAULTRULE",                                 // 89
    "PROERTYDEFINITION",                              // 90
    "SITE",                                           // 91
    "SPACING",                                        // 92
    "VIA",                                            // 93
    "VIARULE",                                        // 94
    "VIARULEGEN",                                     // 95
    "UNITS",                                          // 96
    "ANTENNAINPUTGATEAREA",                           // 97
    "ANTENNAINOUTDIFFAREA",                           // 98
    "ANTENNAOUTPUTDIFFAREA",                          // 99
    "ANTENNAMODEL",                                   // 100
    "ANTENNAAREARATIO",                               // 101
    "ANTENNADIFFAREARATIO",                           // 102
    "ANTENNADIFFAREARATIO PWL",                       // 103
    "ANTENNACUMAREARATIO",                            // 104
    "ANTENNACUMDIFFAREARATIO",                        // 105
    "ANTENNACUMDIFFAREARATIO PWL",                    // 106
    "ANTENNAAREAFACTOR",                              // 107
    "ANTENNASIDEAREARATIO",                           // 108
    "ANTENNADIFFSIDEAREARATIO",                       // 109
    "ANTENNADIFFSIDEAREARATIO PWL",                   // 110
    "ANTENNACUMSIDEAREARATIO",                        // 111
    "ANTENNACUMDIFFSIDEAREARATIO",                    // 112
    "ANTENNACUMDIFFSIDEAREARATIO PWL",                // 113
    "ANTENNASIDEAREAFACTOR",                          // 114
    "ANTENNAPARTIALMETALAREA",                        // 115
    "ANTENNAPARTIALMETALSIDEAREA",                    // 116
    "ANTENNAGATEAREA",                                // 117
    "ANTENNADIFFAREA",                                // 118
    "ANTENNAMAXAREACAR",                              // 119
    "ANTENNAMAXSIDEAREACAR",                          // 120
    "ANTENNAPARTIALCUTAREA",                          // 121
    "ANTENNAMAXCUTCAR",                               // 122
    "CLEARANCEMEASURE",                               // 123
    "DENSITYCHECKWINDOW",                             // 124
    "DENSITYCHECKSTEP",                               // 125
    "DESIGNRULEWIDTH",                                // 126
    "FILLACTIVESPACING",                              // 127
    "MANUFACTURINGGRID",                              // 128
    "MAXADJACENTSLOTSPACING",                         // 129
    "MAXCOAXIALSLOTSPACING",                          // 130
    "MAXEDGESLOTSPACING",                             // 131
    "MAXIMUMDENSITY",                                 // 132
    "MINIMUMDENSITY",                                 // 133
    "ROWABUTSPACING",                                 // 134
    "ROWMINSPACING",                                  // 135
    "SLOTWIREWIDTH",                                  // 136
    "SLOTWIRELENGTH",                                 // 137
    "SLOTWIDTH",                                      // 138
    "SLOTLENGTH",                                     // 139
    "SPLITWIREWIDTH",                                 // 140
    "USEMINSPACING PIN"                               // 141
};

// internal function
char* lefwAddr(const char* x)
{
  return (char*) x;
}

// internal function
char* lefwOrient(int num)
{
  switch (num) {
    case 0:
      return lefwAddr("N");
    case 1:
      return lefwAddr("W");
    case 2:
      return lefwAddr("S");
    case 3:
      return lefwAddr("E");
    case 4:
      return lefwAddr("FN");
    case 5:
      return lefwAddr("FW");
    case 6:
      return lefwAddr("FS");
    case 7:
      return lefwAddr("FE");
  };
  return lefwAddr("BOGUS");
}

// internal function
bool lefwValidateMaskNumber(int num)
{
  int digit = 0;
  int index = 0;

  if (num < 0) {
    return false;
  }

  while (num > 0) {
    digit = num % 10;

    if (digit > 3) {
      return false;
    }

    index++;
    num = num / 10;
  }

  if (index > 3) {
    return false;
  }

  return true;
}

// this function is required to be called first to initialize the array
// Either this function or lefwInitCbk can be called, cannot be both
int lefwInit(FILE* f)
{
  int i;

  lefwFile = f;

  if (lefwHasInitCbk == 1) {  // lefwInitCbk has already called, issue an error
    fprintf(lefwFile,
            "ERROR (LEFWRIT-4000): lefwInitCbk has already called, cannot call "
            "lefwInit again.\n");
    fprintf(lefwFile, "Writer Exit.\n");
    exit(LEFW_BAD_ORDER);
  }
  lefwState = LEFW_UNINIT;  // Current state of writer
  lefwDidInit = 0;          // required section

  for (i = 0; i < MAXSYN; i++) {
    lefwSynArray[i] = 0;
  }

  lefwDidInit = 1;
  lefwState = LEFW_INIT;
  lefwHasInit = 1;
  return LEFW_OK;
}

// this function is required to be called first to initialize the array
// Either this function or lefwInit can be called, cannot be both
int lefwInitCbk(FILE* f)
{
  int i;

  // if (lefwFile) return LEFW_BAD_ORDER;
  lefwFile = f;

  if (lefwHasInit == 1) {  // lefwInit has already called, issue an error
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*)
                     "ERROR (LEFWRIT-4001): lefwInit has already called, cannot call lefwInitCbk again.\n");
      encPrint(lefwFile, (char*) "Writer Exit.\n");
    } else {
      fprintf(lefwFile,
              "ERROR (LEFWRIT-4002): lefwInit has already called, cannot call "
              "lefwInitCbk again.\n");
      fprintf(lefwFile, "Writer Exit.\n");
    }
    exit(LEFW_BAD_ORDER);
  }
  lefwState = LEFW_UNINIT;  // Current state of writer
  lefwDidInit = 0;          // required section

  for (i = 0; i < MAXSYN; i++) {
    lefwSynArray[i] = 0;
  }

  lefwDidInit = 1;
  lefwState = LEFW_INIT;
  lefwHasInitCbk = 1;
  return LEFW_OK;
}

// This function sets the global variable lefwEncrypt to 1, which will
// write out an output encrypted file, make sure to call lefwCloseEncrypt
// before closing the output file
int lefwEncrypt()
{
  if (!lefwFile || (lefwFile == stdout)) {
    // No output filename is given
    fprintf(stderr,
            "ERROR (LEFWRITE-4006): Need an output file if writing in "
            "encrypted format.\n");
    return LEFW_BAD_ORDER;
  }

  // Set the flag in crypt.cpp
  encWritingEncrypted();

  lefwWriteEncrypt = 1;
  return LEFW_OK;
}

// This function needs to be called if lefwEncrypt is called
// It will clear the encrypted buffer
int lefwCloseEncrypt()
{
  if (lefwWriteEncrypt) {
    encClearBuf(lefwFile);
  }
  return LEFW_OK;
}

int lefwNewLine()
{
  if (!lefwFile) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n");
  } else {
    fprintf(lefwFile, "\n");
  }
  return LEFW_OK;
}

int lefwVersion(int vers1, int vers2)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_VERSION]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "VERSION %d.%d ;\n", vers1, vers2);
  } else {
    fprintf(lefwFile, "VERSION %d.%d ;\n", vers1, vers2);
  }
  if (vers2 >= 10) {
    versionNum = vers1 + (vers2 / 100.0);
  } else {
    versionNum = vers1 + (vers2 / 10.0);
  }
  lefwSynArray[LEFW_VERSION] = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwCaseSensitive(const char* caseSensitive)
{
  lefwObsoleteNum = LEFW_CASESENSITIVE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (lefwSynArray[LEFW_CASESENSITIVE]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (strcmp(caseSensitive, "ON") && strcmp(caseSensitive, "OFF")) {
    return LEFW_BAD_DATA;  // has to be either ON or OFF
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "NAMESCASESENSITIVE %s ;\n", caseSensitive);
  } else {
    fprintf(lefwFile, "NAMESCASESENSITIVE %s ;\n", caseSensitive);
  }
  lefwSynArray[LEFW_CASESENSITIVE] = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwNoWireExtensionAtPin(const char* noWireExt)
{
  lefwObsoleteNum = LEFW_NOWIREEXTATPIN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (lefwSynArray[LEFW_NOWIREEXTATPIN]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (strcmp(noWireExt, "ON") && strcmp(noWireExt, "OFF")) {
    return LEFW_BAD_DATA;  // has to be either ON or OFF
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "NOWIREEXTENSIONATPIN %s ;\n", noWireExt);
  } else {
    fprintf(lefwFile, "NOWIREEXTENSIONATPIN %s ;\n", noWireExt);
  }
  lefwSynArray[LEFW_NOWIREEXTATPIN] = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwMinfeature(double minFeatureX, double minFeatureY)
{
  lefwObsoleteNum = LEFW_MINFEATURE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwSynArray[LEFW_MINFEATURE]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "MINFEATURE %.11g %.11g ;\n",
             minFeatureX,
             minFeatureY);
  } else {
    fprintf(lefwFile, "MINFEATURE %.11g %.11g ;\n", minFeatureX, minFeatureY);
  }
  lefwSynArray[LEFW_MINFEATURE] = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwDielectric(double dielectric)
{
  lefwObsoleteNum = LEFW_DIELECTRIC;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwSynArray[LEFW_DIELECTRIC]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "DIELECTRIC %.11g ;\n", dielectric);
  } else {
    fprintf(lefwFile, "DIELECTRIC %.11g ;\n", dielectric);
  }
  lefwSynArray[LEFW_DIELECTRIC] = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwBusBitChars(const char* busBitChars)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_BUSBITCHARS]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (busBitChars && busBitChars != nullptr && *busBitChars != 0) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "BUSBITCHARS \"%s\" ;\n", busBitChars);
    } else {
      fprintf(lefwFile, "BUSBITCHARS \"%s\" ;\n", busBitChars);
    }
  }
  lefwLines++;
  lefwSynArray[LEFW_BUSBITCHARS] = 1;
  return LEFW_OK;
}

int lefwDividerChar(const char* dividerChar)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_DIVIDERCHAR]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (dividerChar && dividerChar != nullptr && *dividerChar != 0) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "DIVIDERCHAR \"%s\" ;\n", dividerChar);
    } else {
      fprintf(lefwFile, "DIVIDERCHAR \"%s\" ;\n", dividerChar);
    }
  }
  lefwLines++;
  lefwSynArray[LEFW_DIVIDERCHAR] = 1;
  return LEFW_OK;
}

int lefwManufacturingGrid(double grid)
{
  lefw54Num = LEFW_MANUFACTURINGGRID;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_MANUFACTURINGGRID]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "MANUFACTURINGGRID %.11g ;\n", grid);
  } else {
    fprintf(lefwFile, "MANUFACTURINGGRID %.11g ;\n", grid);
  }
  lefwLines++;
  lefwSynArray[LEFW_MANUFACTURINGGRID] = 1;
  return LEFW_OK;
}

int lefwFixedMask()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }

  if (versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "FIXEDMASK ;\n");
  } else {
    fprintf(lefwFile, "FIXEDMASK ;\n");
  }

  lefwLines++;
  lefwSynArray[LEFW_FIXEDMASK] = 1;
  return LEFW_OK;
}

int lefwUseMinSpacing(const char* type, const char* onOff)
{
  lefwObsoleteNum = LEFW_USEMINSPACING;
  lefw54Num = LEFW_USEMINSPACING;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  // Can define more than once
  // if (lefwSynArray[LEFW_USEMINSPACING]) return LEFW_ALREADY_DEFINED;
  if (!type || (strcmp(type, "OBS") && strcmp(type, "PIN"))) {
    return LEFW_BAD_DATA;  // has to be OBS or PIN
  }
  if ((strcmp(type, "PIN") == 0) && (versionNum >= 5.6)) {
    return LEFW_OBSOLETE;
  }
  if (!onOff || (strcmp(onOff, "ON") && strcmp(onOff, "OFF"))) {
    return LEFW_BAD_DATA;  // has to be ON or OFF
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "USEMINSPACING %s %s ;\n", type, onOff);
  } else {
    fprintf(lefwFile, "USEMINSPACING %s %s ;\n", type, onOff);
  }
  lefwLines++;
  // lefwSynArray[LEFW_USEMINSPACING] = 1;
  return LEFW_OK;
}

int lefwClearanceMeasure(const char* type)
{
  lefw54Num = LEFW_CLEARANCEMEASURE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_CLEARANCEMEASURE]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (!type || (strcmp(type, "MAXXY") && strcmp(type, "EUCLIDEAN"))) {
    return LEFW_BAD_DATA;  // has to be MAXXY or EUCLIDEAN
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "CLEARANCEMEASURE %s ;\n", type);
  } else {
    fprintf(lefwFile, "CLEARANCEMEASURE %s ;\n", type);
  }
  lefwLines++;
  lefwSynArray[LEFW_CLEARANCEMEASURE] = 1;
  return LEFW_OK;
}

int lefwStartUnits()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwSynArray[LEFW_UNITS_START]) {
    return LEFW_ALREADY_DEFINED;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "UNITS\n");
  } else {
    fprintf(lefwFile, "UNITS\n");
  }
  lefwLines++;
  lefwSynArray[LEFW_UNITS_START] = 1;
  lefwState = LEFW_UNITS_START;
  return LEFW_OK;
}

int lefwUnits(double time,         // optional
              double capacitance,  // optional
              double resistance,   // optional
              double power,        // optional
              double current,      // optional
              double voltage,      // optional
              double database      // optional
)
{
  int databaseVal;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_UNITS_START && lefwState != LEFW_UNITS) {
    return LEFW_BAD_ORDER;
  }

  if (time) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   TIME NANOSECONDS %.11g ;\n", time);
    } else {
      fprintf(lefwFile, "   TIME NANOSECONDS %.11g ;\n", time);
    }
  }
  if (capacitance) {
    if (lefwWriteEncrypt) {
      encPrint(
          lefwFile, (char*) "   CAPACITANCE PICOFARADS %.11g ;\n", capacitance);
    } else {
      fprintf(lefwFile, "   CAPACITANCE PICOFARADS %.11g ;\n", capacitance);
    }
  }
  if (resistance) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   RESISTANCE OHMS %.11g ;\n", resistance);
    } else {
      fprintf(lefwFile, "   RESISTANCE OHMS %.11g ;\n", resistance);
    }
  }
  if (power) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   POWER MILLIWATTS %.11g ;\n", power);
    } else {
      fprintf(lefwFile, "   POWER MILLIWATTS %.11g ;\n", power);
    }
  }
  if (current) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   CURRENT MILLIAMPS %.11g ;\n", current);
    } else {
      fprintf(lefwFile, "   CURRENT MILLIAMPS %.11g ;\n", current);
    }
  }
  if (voltage) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   VOLTAGE VOLTS %.11g ;\n", voltage);
    } else {
      fprintf(lefwFile, "   VOLTAGE VOLTS %.11g ;\n", voltage);
    }
  }
  if (database) {
    databaseVal = (int) database;
    switch (databaseVal) {
      case 100:
      case 200:
      case 1000:
      case 2000:
      case 10000:
      case 20000:
        if (lefwWriteEncrypt) {
          encPrint(lefwFile, (char*) "   DATABASE MICRONS %d ;\n", database);
        } else {
          fprintf(lefwFile, "   DATABASE MICRONS %d ;\n", databaseVal);
        }
        break;
      default:
        return LEFW_BAD_DATA;
    }
  }

  lefwState = LEFW_UNITS;
  return LEFW_OK;
}

int lefwUnitsFrequency(double frequency)
{  // required since only by itself

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_UNITS_START && lefwState != LEFW_UNITS) {
    return LEFW_BAD_ORDER;
  }
  if (!frequency) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FREQUENCY MEGAHERTZ %.11g ;\n", frequency);
  } else {
    fprintf(lefwFile, "   FREQUENCY MEGAHERTZ %.11g ;\n", frequency);
  }

  lefwState = LEFW_UNITS;
  return LEFW_OK;
}

int lefwEndUnits()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_UNITS_START && lefwState != LEFW_UNITS) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END UNITS\n\n");
  } else {
    fprintf(lefwFile, "END UNITS\n\n");
  }
  lefwLines++;
  lefwState = LEFW_UNITS_END;
  return LEFW_OK;
}

int lefwStartLayer(const char* layerName, const char* type)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_LAYER_START || lefwState == LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (strcmp(type, "CUT") == 0) {
    lefwIsCut = 1;
  } else if (strcmp(type, "IMPLANT") == 0) {  // IMPLANT is 5.5 syntax
    lefwIsImplant = 1;
  } else if (strcmp(type, "MASTERSLICE") && strcmp(type, "OVERLAP")
             && strcmp(type, "IMPLANT")) {  // IMPLANT is 5.5 syntax
    return LEFW_BAD_DATA;  // type is CUT, MASTERSLICE or OVERLAP only
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "LAYER %s\n", layerName);
    encPrint(lefwFile, (char*) "   TYPE %s ;\n", type);
  } else {
    fprintf(lefwFile, "LAYER %s\n", layerName);
    fprintf(lefwFile, "   TYPE %s ;\n", type);
  }
  lefwIsRouting = 0;
  lefwLines = lefwLines + 2;
  lefwState = LEFW_LAYER_START;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacing(double spacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;
  }
  if ((!lefwIsCut) && (!lefwIsImplant)) {
    return LEFW_BAD_DATA;
  }
  // only cut & implant call this func
  if (spacing) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   SPACING %.11g", spacing);
    } else {
      fprintf(lefwFile, "   SPACING %.11g", spacing);
    }
  } else {
    return LEFW_BAD_ORDER;
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  lefwIsLayerCutSpacing = 1;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingCenterToCenter()
{
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     CENTERTOCENTER");
  } else {
    fprintf(lefwFile, "\n     CENTERTOCENTER");
  }
  lefwLines++;

  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingSameNet()
{
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     SAMENET");
  } else {
    fprintf(lefwFile, "\n     SAMENET");
  }
  lefwLines++;

  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingLayer(const char* name2, int stack)
{  // optional
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     LAYER %s", name2);
    if (stack) {
      encPrint(lefwFile, (char*) " STACK");
    }
  } else {
    fprintf(lefwFile, "\n     LAYER %s", name2);
    if (stack) {
      fprintf(lefwFile, " STACK");
    }
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingAdjacent(int viaCuts,  // either 2, 3 or 4, optional
                                double distance,
                                int except)
{  // optional
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    if (viaCuts < 2 || viaCuts > 4) {
      return LEFW_BAD_DATA;
    }
    encPrint(lefwFile,
             (char*) "\n     ADJACENTCUTS %d WITHIN %.11g",
             viaCuts,
             distance);
    if (except) {
      encPrint(lefwFile, (char*) " EXCEPTSAMEPGNET");
    }

  } else {
    if (viaCuts < 2 || viaCuts > 4) {
      return LEFW_BAD_DATA;
    }
    fprintf(lefwFile, "\n     ADJACENTCUTS %d WITHIN %.11g", viaCuts, distance);
    if (except) {
      fprintf(lefwFile, " EXCEPTSAMEPGNET");
    }
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingParallel()
{
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     PARALLELOVERLAP");
  } else {
    fprintf(lefwFile, "\n     PARALLELOVERLAP");
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingArea(double cutArea)
{
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     AREA %.11g", cutArea);
  } else {
    fprintf(lefwFile, "\n     AREA %.11g", cutArea);
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingEnd()
{
  if (!lefwIsLayerCutSpacing) {
    return LEFW_BAD_ORDER;  // has to be after
  }
  // lefwLayerCutSpacing is called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) " ;\n");
  } else {
    fprintf(lefwFile, " ;\n");
  }

  lefwIsLayerCutSpacing = 0;
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

int lefwLayerMask(int colorMask)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER
      && lefwState != LEFW_LAYERROUTING_START) {
    return LEFW_BAD_ORDER;
  }

  if (versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(colorMask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MASK %d ;\n", colorMask);
  } else {
    fprintf(lefwFile, "   MASK %d ;\n", colorMask);
  }

  lefwLines++;

  lefwState
      = (lefwState == LEFW_LAYERROUTING_START) ? LEFW_LAYERROUTING : LEFW_LAYER;

  return LEFW_OK;
}

int lefwLayerWidth(double minWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if ((!lefwIsImplant) && (!lefwIsCut)) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   WIDTH %.11g ;\n", minWidth);
  } else {
    fprintf(lefwFile, "   WIDTH %.11g ;\n", minWidth);
  }

  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerCutSpacingTableOrtho(int numSpacing,
                                  double* cutWithins,
                                  double* orthoSpacings)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (numSpacing) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   SPACINGTABLE ORTHOGONAL");
      lefwLines++;
      for (i = 0; i < numSpacing; i++) {
        encPrint(lefwFile,
                 (char*) "\n     WITHING %.11g SPACING %.11g ",
                 *cutWithins++,
                 *orthoSpacings++);
        lefwLines++;
      }
      encPrint(lefwFile, (char*) " ;\n");
    } else {
      fprintf(lefwFile, "   SPACINGTABLE ORTHOGONAL");
      lefwLines++;
      for (i = 0; i < numSpacing; i++) {
        fprintf(lefwFile,
                "\n     WITHIN %.11g SPACING %.11g",
                *cutWithins++,
                *orthoSpacings++);
        lefwLines++;
      }
      fprintf(lefwFile, " ;\n");
    }
  }
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerArraySpacing(int longArray,
                          double viaWidth,
                          double cutSpacing,
                          int numArrayCut,
                          int* arrayCuts,
                          double* arraySpacings)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (cutSpacing) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   ARRAYSPACING ");
      if (longArray) {
        encPrint(lefwFile, (char*) "LONGARRAY ");
      }
      if (viaWidth) {
        encPrint(lefwFile, (char*) "WIDTH %.11g ", viaWidth);
      }
      encPrint(lefwFile, (char*) "CUTSPACING %.11g ", cutSpacing);
      for (i = 0; i < numArrayCut; i++) {
        encPrint(lefwFile,
                 (char*) "ARRAYCUTS %d SPACING %.11g ",
                 *arrayCuts++,
                 *arraySpacings++);
      }
      encPrint(lefwFile, (char*) " ;\n");
    } else {
      fprintf(lefwFile, "  ARRAYSPACING ");
      if (longArray) {
        fprintf(lefwFile, "LONGARRAY ");
      }
      if (viaWidth) {
        fprintf(lefwFile, "WIDTH %.11g ", viaWidth);
      }
      fprintf(lefwFile, "CUTSPACING %.11g ", cutSpacing);
      for (i = 0; i < numArrayCut; i++) {
        fprintf(lefwFile,
                "ARRAYCUTS %d SPACING %.11g ",
                *arrayCuts++,
                *arraySpacings++);
      }
      fprintf(lefwFile, " ;\n");
    }
    lefwLines++;
  }
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

int lefwLayerEnclosure(const char* location,
                       double overhang1,
                       double overhang2,
                       double width)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        encPrint(lefwFile,
                 (char*) "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      encPrint(lefwFile, (char*) "%s ", location);
    }
    encPrint(lefwFile, (char*) "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      encPrint(lefwFile, (char*) "WIDTH %.11g ", width);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        fprintf(lefwFile,
                "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      fprintf(lefwFile, "%s ", location);
    }
    fprintf(lefwFile, "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      fprintf(lefwFile, "WIDTH %.11g ", width);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerEnclosureWidth(const char* location,
                            double overhang1,
                            double overhang2,
                            double width,  // optional
                            double cutWithin)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        encPrint(lefwFile,
                 (char*) "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      encPrint(lefwFile, (char*) "%s ", location);
    }
    encPrint(lefwFile, (char*) "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      encPrint(lefwFile, (char*) "WIDTH %.11g ", width);
      if (cutWithin) {
        encPrint(lefwFile, (char*) "EXCEPTEXTRACUT %.11g ", cutWithin);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        fprintf(lefwFile,
                "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      fprintf(lefwFile, "%s ", location);
    }
    fprintf(lefwFile, "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      fprintf(lefwFile, "WIDTH %.11g ", width);
      if (cutWithin) {
        fprintf(lefwFile, "EXCEPTEXTRACUT %.11g ", cutWithin);
      }
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

// 5.7
int lefwLayerEnclosureLength(const char* location,
                             double overhang1,
                             double overhang2,
                             double minLength)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        encPrint(lefwFile,
                 (char*) "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      encPrint(lefwFile, (char*) "%s ", location);
    }
    encPrint(lefwFile, (char*) "%.11g %.11g ", overhang1, overhang2);
    if (minLength) {
      encPrint(lefwFile, (char*) "LENGTH %.11g ", minLength);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   ENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        fprintf(lefwFile,
                "ENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      fprintf(lefwFile, "%s ", location);
    }
    fprintf(lefwFile, "%.11g %.11g ", overhang1, overhang2);
    if (minLength) {
      fprintf(lefwFile, "LENGTH %.11g ", minLength);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

int lefwLayerPreferEnclosure(const char* location,
                             double overhang1,
                             double overhang2,
                             double width)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   PREFERENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        encPrint(
            lefwFile,
            (char*) "PREFERENCLOSURE in Layer(Cut) can only be ABOVE, "
                    "BELOW.\n");
        return LEFW_BAD_DATA;
      }
      encPrint(lefwFile, (char*) "%s ", location);
    }
    encPrint(lefwFile, (char*) "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      encPrint(lefwFile, (char*) "WIDTH %.11g ", width);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   PREFERENCLOSURE ");
    if (location && (*location != 0)) {
      if (strcmp(location, "ABOVE") && strcmp(location, "BELOW")) {
        fprintf(lefwFile,
                "PREFERENCLOSURE in Layer(Cut) can only be ABOVE, BELOW.\n");
        return LEFW_BAD_DATA;
      }
      fprintf(lefwFile, "%s ", location);
    }
    fprintf(lefwFile, "%.11g %.11g ", overhang1, overhang2);
    if (width) {
      fprintf(lefwFile, "WIDTH %.11g ", width);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

int lefwLayerResistancePerCut(double resistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsCut) {
    return LEFW_BAD_DATA;  // only cut calls this func
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;  // Layer after maximum stacked-via
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   RESISTANCEPERCUT %.11g ;\n", resistance);
  } else {
    fprintf(lefwFile, "   RESISTANCEPERCUT %.11g ;\n", resistance);
  }
  lefwLines++;
  lefwState = LEFW_LAYER;
  return LEFW_OK;
}

int lefwEndLayer(const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", layerName);
  } else {
    fprintf(lefwFile, "END %s\n\n", layerName);
  }

  lefwLines++;
  lefwState = LEFW_LAYER_END;
  lefwIsCut = 0;
  lefwIsImplant = 0;
  return LEFW_OK;
}

int lefwStartLayerRouting(const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_LAYERROUTING_START || lefwState == LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "LAYER %s\n", layerName);
    encPrint(lefwFile, (char*) "   TYPE ROUTING ;\n");
  } else {
    fprintf(lefwFile, "LAYER %s\n", layerName);
    fprintf(lefwFile, "   TYPE ROUTING ;\n");
  }
  lefwIsRouting = 1;
  lefwIsRoutingReqData = 0;
  lefwLines = lefwLines + 2;
  lefwState = LEFW_LAYERROUTING_START;
  lefwSynArray[LEFW_LAYERROUTING_START] = 1;

  return LEFW_OK;
}

int lefwLayerRouting(const char* direction, double width)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  // this routine should call only once per layer routing
  if (lefwSynArray[LEFW_LAYERROUTING]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    if (!direction || direction == nullptr || *direction == 0) {
      encPrint(lefwFile, (char*) "DIRECTION is required in Layer(Routing).\n");
      return LEFW_BAD_DATA;
    }
    if (strcmp(direction, "HORIZONTAL") && strcmp(direction, "VERTICAL")
        && strcmp(direction, "DIAG45") && strcmp(direction, "DIAG135")) {
      encPrint(lefwFile, (char*)
                     "DIRECTION in Layer(Routing) can only be HORIZONTAL, VERTICAL, DIAG45, DIAG135.\n");
      return LEFW_BAD_DATA;  // direction is either HORIZONTAL, VERTICAL,
                             // DIAG45, DIAG135 only
    }
    encPrint(lefwFile, (char*) "   DIRECTION %s ;\n", direction);
    encPrint(lefwFile, (char*) "   WIDTH %.11g ;\n", width);
  } else {
    if (!direction || direction == nullptr || *direction == 0) {
      fprintf(lefwFile, "DIRECTION is required in Layer(Routing).\n");
      return LEFW_BAD_DATA;
    }
    if (strcmp(direction, "HORIZONTAL") && strcmp(direction, "VERTICAL")
        && strcmp(direction, "DIAG45") && strcmp(direction, "DIAG135")) {
      fprintf(lefwFile,
              "DIRECTION in Layer(Routing) can only be HORIZONTAL, VERTICAL, "
              "DIAG45, DIAG135.\n");
      return LEFW_BAD_DATA;  // direction is either HORIZONTAL, VERTICAL,
                             // DIAG45, DIAG135 only
    }
    fprintf(lefwFile, "   DIRECTION %s ;\n", direction);
    fprintf(lefwFile, "   WIDTH %.11g ;\n", width);
  }

  lefwLines += 2;
  lefwIsRoutingReqData = 1;
  lefwSynArray[LEFW_LAYERROUTING] = 1;
  lefwIsRoutingMinCut = 0;
  return LEFW_OK;
}

int lefwLayerRoutingPitch(double pitch)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  // this routine should call only once per layer routing
  // it is required for SE only, other is optional
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   PITCH %.11g ;\n", pitch);
  } else {
    fprintf(lefwFile, "   PITCH %.11g ;\n", pitch);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingPitchXYDistance(double xDistance, double yDistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  // this routine should call only once per layer routing
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   PITCH %.11g %.11g ;\n", xDistance, yDistance);
  } else {
    fprintf(lefwFile, "   PITCH %.11g %.11g ;\n", xDistance, yDistance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingOffset(double offset)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   OFFSET %.11g ;\n", offset);
  } else {
    fprintf(lefwFile, "   OFFSET %.11g ;\n", offset);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingOffsetXYDistance(double xDistance, double yDistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   OFFSET %.11g %.11g ;\n", xDistance, yDistance);
  } else {
    fprintf(lefwFile, "   OFFSET %.11g %.11g ;\n", xDistance, yDistance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingDiagPitch(double distance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DIAGPITCH %.11g ;\n", distance);
  } else {
    fprintf(lefwFile, "   DIAGPITCH %.11g ;\n", distance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingDiagPitchXYDistance(double xDistance, double yDistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   DIAGPITCH %.11g %.11g ;\n", xDistance, yDistance);
  } else {
    fprintf(lefwFile, "   DIAGPITCH %.11g %.11g ;\n", xDistance, yDistance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingDiagWidth(double diagWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  // this routine should call only once per layer routing
  // it is required for SE only, other is optional
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DIAGWIDTH %.11g ;\n", diagWidth);
  } else {
    fprintf(lefwFile, "   DIAGWIDTH %.11g ;\n", diagWidth);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingDiagSpacing(double diagSpacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  // this routine should call only once per layer routing
  // it is required for SE only, other is optional
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DIAGSPACING %.11g ;\n", diagSpacing);
  } else {
    fprintf(lefwFile, "   DIAGSPACING %.11g ;\n", diagSpacing);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingDiagMinEdgeLength(double diagLength)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  // this routine should call only once per layer routing
  // it is required for SE only, other is optional
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DIAGMINEDGELENGTH %.11g ;\n", diagLength);
  } else {
    fprintf(lefwFile, "   DIAGMINEDGELENGTH %.11g ;\n", diagLength);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingArea(double area)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   AREA %.11g ;\n", area);
  } else {
    fprintf(lefwFile, "   AREA %.11g ;\n", area);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinsize(int numRect, double* minWidth, double* minLength)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINSIZE ");
    for (i = 0; i < numRect; i++) {
      encPrint(lefwFile, (char*) "%.11g %.11g ", minWidth[i], minLength[i]);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   MINSIZE ");
    for (i = 0; i < numRect; i++) {
      fprintf(lefwFile, "%.11g %.11g ", minWidth[i], minLength[i]);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinimumcut(double numCuts, double minWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   MINIMUMCUT %.11g WIDTH %.11g ",
             numCuts,
             minWidth);
  } else {
    fprintf(lefwFile, "   MINIMUMCUT %.11g WIDTH %.11g ", numCuts, minWidth);
  }
  lefwLines++;
  prtSemiColon = 1;
  lefwIsRoutingMinCut = 1;
  lefwIsRoutingMinCutDist = 0;
  lefwIsRoutingMinCutLen = 0;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingMinimumcutWithin(double numCuts,
                                     double minWidth,
                                     double cutDistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   MINIMUMCUT %.11g WIDTH %.11g WITHIN %.11g ",
             numCuts,
             minWidth,
             cutDistance);
  } else {
    fprintf(lefwFile,
            "   MINIMUMCUT %.11g WIDTH %.11g WITHIN %.11g ",
            numCuts,
            minWidth,
            cutDistance);
  }
  lefwLines++;
  prtSemiColon = 1;
  lefwIsRoutingMinCut = 1;
  lefwIsRoutingMinCutDist = 0;
  lefwIsRoutingMinCutLen = 0;
  return LEFW_OK;
}

int lefwLayerRoutingMinimumcutConnections(const char* direction)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsRoutingMinCut || lefwIsRoutingMinCutDist) {
    return LEFW_BAD_ORDER;
  }
  // lefwLayerRoutingMinimumcut has not being called or
  // lefwLayerRoutingMinimumcutConnections has already called
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     %s ", direction);
  } else {
    fprintf(lefwFile, "\n     %s ", direction);
  }
  lefwLines++;
  prtSemiColon = 1;
  lefwIsRoutingMinCutDist = 1;
  if (lefwIsRoutingMinCutLen) {  // both distance & length within has defined
    lefwIsRoutingMinCut = 0;
  }
  return LEFW_OK;
}

int lefwLayerRoutingMinimumcutLengthWithin(double length, double distance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsRoutingMinCut || lefwIsRoutingMinCutLen) {
    return LEFW_BAD_ORDER;
  }
  // lefwLayerRoutingMinimumcut has not being called or
  // lefwLayerRoutingMinimumcutLengthWithin has already called
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "     LENGTH %.11g WITHIN %.11g ", length, distance);
  } else {
    fprintf(lefwFile, "     LENGTH %.11g WITHIN %.11g ", length, distance);
  }
  lefwLines++;
  prtSemiColon = 1;
  lefwIsRoutingMinCutLen = 1;
  if (lefwIsRoutingMinCutDist) {  // both distance & length within has defined
    lefwIsRoutingMinCut = 0;
  }
  return LEFW_OK;
}

int lefwLayerRoutingSpacing(double spacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SPACING %.11g ", spacing);
  } else {
    fprintf(lefwFile, "   SPACING %.11g ", spacing);
  }
  lefwLines++;
  lefwHasLayerRoutingRange = 0;    // initialization
  lefwHasLayerRoutingSpacing = 1;  // initialization
  lefwHasLayerRoutingEol = 0;      // initialization
  prtNewLine = 1;
  prtSemiColon = 1;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingRange(double leftRange, double rightRange)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingSpacing) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", leftRange, rightRange);
  } else {
    fprintf(lefwFile, "RANGE %.11g %.11g ", leftRange, rightRange);
  }
  lefwHasLayerRoutingRange = 1;  // initialization
  lefwLines++;
  prtNewLine = 1;
  prtSemiColon = 1;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingRangeUseLengthThreshold()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingRange) {
    // This routine can be called only if range are non zero
    fprintf(lefwFile,
            "ERROR (LEFWRIT-4003): lefwLayerRoutingSpacingUseLengthThreshold "
            "cannot be called if\n");
    fprintf(lefwFile,
            "       lefwLayerRoutingSpacingRange has not been called.\n");
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     USELENGTHTHRESHOLD ");
  } else {
    fprintf(lefwFile, "\n     USELENGTHTHRESHOLD ");
  }
  prtSemiColon = 1;
  prtNewLine = 1;
  lefwHasLayerRoutingRange = 0;  // reset to 0
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingRangeInfluence(double infValue,
                                          double subMinWidth,
                                          double subMaxWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingRange) {
    // This routine can be called only if range are non zero
    fprintf(lefwFile,
            "ERROR (LEFWRIT-4004): lefwLayerRoutingSpacingInfluence cannot be "
            "called if\n");
    fprintf(lefwFile,
            "       lefRange and rightRange in lefwLayerRoutingSpacing are "
            "both zero.\n");
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n     INFLUENCE %.11g ", infValue);
    if (subMinWidth || subMaxWidth) {
      encPrint(
          lefwFile, (char*) "RANGE %.11g %.11g ", subMinWidth, subMaxWidth);
    }
  } else {
    fprintf(lefwFile, "\n     INFLUENCE %.11g ", infValue);
    if (subMinWidth || subMaxWidth) {
      fprintf(lefwFile, (char*) "RANGE %.11g %.11g ", subMinWidth, subMaxWidth);
    }
  }
  prtNewLine = 1;
  prtSemiColon = 1;
  lefwHasLayerRoutingRange = 0;  // reset to 0
  return LEFW_OK;
}

int lefwLayerRoutingSpacingRangeRange(double minWidth, double maxWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingRange) {
    // This routine can be called only if range are non zero
    fprintf(lefwFile,
            "ERROR (LEFWRIT-4005): lefwLayerRoutingSpacingInfluence cannot be "
            "called if\n");
    fprintf(lefwFile,
            "       lefRange and rightRange in lefwLayerRoutingSpacing are "
            "both zero.\n");
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", minWidth, maxWidth);
  } else {
    fprintf(lefwFile, (char*) "RANGE %.11g %.11g ", minWidth, maxWidth);
  }
  prtNewLine = 1;
  prtSemiColon = 1;
  lefwHasLayerRoutingRange = 0;  // reset to 0
  return LEFW_OK;
}

int lefwLayerRoutingSpacingLengthThreshold(double lengthValue,
                                           double minWidth,
                                           double maxWidth)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingSpacing) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LENGTHTHRESHOLD %.11g ", lengthValue);
    if (minWidth || maxWidth) {
      encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", minWidth, maxWidth);
    }
  } else {
    fprintf(lefwFile, "   LENGTHTHRESHOLD %.11g ", lengthValue);
    if (minWidth || maxWidth) {
      fprintf(lefwFile, "RANGE %.11g %.11g ", minWidth, maxWidth);
    }
  }
  prtSemiColon = 1;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingSpacingSameNet(int PGOnly)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!lefwHasLayerRoutingSpacing) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    if (PGOnly) {
      encPrint(lefwFile, (char*) "   SAMENET PGONLY ");
    } else {
      encPrint(lefwFile, (char*) "   SAMENET ");
    }
  } else {
    if (PGOnly) {
      fprintf(lefwFile, "   SAMENET PGONLY ");
    } else {
      fprintf(lefwFile, "   SAMENET ");
    }
  }
  prtSemiColon = 1;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingSpacingEndOfLine(double eolWidth, double eolWithin)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (lefwHasLayerRoutingEol) {
    return LEFW_BAD_DATA;  // already defined in Spacing
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   ENDOFLINE %.11g WITHIN %.11g ",
             eolWidth,
             eolWithin);
  } else {
    fprintf(lefwFile, "   ENDOFLINE %.11g WITHIN %.11g ", eolWidth, eolWithin);
  }
  lefwLines++;
  lefwHasLayerRoutingEol = 1;
  prtSemiColon = 1;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingSpacingEOLParallel(double parSpace,
                                       double parWithin,
                                       int twoEdges)
{
  if (!lefwHasLayerRoutingEol) {
    return LEFW_BAD_DATA;  // EndOfLine in not defined
  }
  if (lefwWriteEncrypt) {
    if (twoEdges) {
      encPrint(lefwFile,
               (char*) "PARALLELEDGE %.11g WITHIN %.11g TWOEDGES ;\n",
               parSpace,
               parWithin);
    } else {
      encPrint(lefwFile,
               (char*) "PARALLELEDGE %.11g WITHIN %.11g ;\n",
               parSpace,
               parWithin);
    }
  } else {
    if (twoEdges) {
      fprintf(lefwFile,
              "PARALLELEDGE %.11g WITHIN %.11g TWOEDGES ;\n",
              parSpace,
              parWithin);
    } else {
      fprintf(
          lefwFile, "PARALLELEDGE %.11g WITHIN %.11g ;\n", parSpace, parWithin);
    }
  }
  lefwLines++;
  lefwHasLayerRoutingEol = 0;
  prtSemiColon = 0;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingSpacingNotchLength(double minNLength)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   NOTCHLENGTH %.11g ;\n", minNLength);
  } else {
    fprintf(lefwFile, "   NOTCHLENGTH %.11g ;\n", minNLength);
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingSpacingEndOfNotchWidth(double eonWidth,
                                           double minNSpacing,
                                           double minNLength)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ENDOFNOTCHWIDTH %.11g NOTCHSPACING %.11g NOTCHLENGTH %.11g ;\n",
                 eonWidth, minNSpacing, minNLength);
  } else {
    fprintf(
        lefwFile,
        "    ENDOFNOTCHWIDTH %.11g NOTCHSPACING %.11g NOTCHLENGTH %.11g ;\n",
        eonWidth,
        minNSpacing,
        minNLength);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingWireExtension(double wireExtension)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   WIREEXTENSION %.11g ;\n", wireExtension);
  } else {
    fprintf(lefwFile, "   WIREEXTENSION %.11g ;\n", wireExtension);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingResistance(const char* resistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (!resistance || resistance == nullptr || *resistance == 0) {
    return LEFW_BAD_DATA;
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   RESISTANCE RPERSQ %s ;\n", resistance);
  } else {
    fprintf(lefwFile, "   RESISTANCE RPERSQ %s ;\n", resistance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingCapacitance(const char* capacitance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (!capacitance || capacitance == nullptr || *capacitance == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   CAPACITANCE CPERSQDIST %s ;\n", capacitance);
  } else {
    fprintf(lefwFile, "   CAPACITANCE CPERSQDIST %s ;\n", capacitance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingHeight(double height)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   HEIGHT %.11g ;\n", height);
  } else {
    fprintf(lefwFile, "   HEIGHT %.11g ;\n", height);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingThickness(double thickness)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   THICKNESS %.11g ;\n", thickness);
  } else {
    fprintf(lefwFile, "   THICKNESS %.11g ;\n", thickness);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingShrinkage(double shrinkage)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SHRINKAGE %.11g ;\n", shrinkage);
  } else {
    fprintf(lefwFile, "   SHRINKAGE %.11g ;\n", shrinkage);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingCapMultiplier(double capMultiplier)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   CAPMULTIPLIER %.11g ;\n", capMultiplier);
  } else {
    fprintf(lefwFile, "   CAPMULTIPLIER %.11g ;\n", capMultiplier);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingEdgeCap(double edgeCap)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   EDGECAPACITANCE %.11g ;\n", edgeCap);
  } else {
    fprintf(lefwFile, "   EDGECAPACITANCE %.11g ;\n", edgeCap);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingAntennaArea(double antennaArea)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNAAREAFACTOR %.11g ;\n", antennaArea);
  } else {
    fprintf(lefwFile, "   ANTENNAAREAFACTOR %.11g ;\n", antennaArea);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingAntennaLength(double antennaLength)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   ANTENNALENGTHFACTOR %.11g ;\n", antennaLength);
  } else {
    fprintf(lefwFile, "   ANTENNALENGTHFACTOR %.11g ;\n", antennaLength);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMaxwidth(double width)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MAXWIDTH %.11g ;\n", width);
  } else {
    fprintf(lefwFile, "   MAXWIDTH %.11g ;\n", width);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinwidth(double width)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINWIDTH %.11g ;\n", width);
  } else {
    fprintf(lefwFile, "   MINWIDTH %.11g ;\n", width);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinenclosedarea(int numMinenclosed,
                                    double* area,
                                    double* width)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    for (i = 0; i < numMinenclosed; i++) {
      encPrint(lefwFile, (char*) "   MINENCLOSEDAREA %.11g ", area[i]);
      if (width[i] != 0) {
        encPrint(lefwFile, (char*) "WIDTH %.11g ", width[i]);
      }
      encPrint(lefwFile, (char*) ";\n");
    }
  } else {
    for (i = 0; i < numMinenclosed; i++) {
      fprintf(lefwFile, "   MINENCLOSEDAREA %.11g ", area[i]);
      if (width[i] != 0) {
        fprintf(lefwFile, "WIDTH %.11g ", width[i]);
      }
      fprintf(lefwFile, ";\n");
    }
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinstep(double distance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINSTEP %.11g ;\n", distance);
  } else {
    fprintf(lefwFile, "   MINSTEP %.11g ;\n", distance);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingMinstepWithOptions(double distance,
                                       const char* rule,
                                       double maxLength)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINSTEP %.11g ", distance);
  } else {
    fprintf(lefwFile, "   MINSTEP %.11g ", distance);
  }
  if (rule
      && ((strcmp(rule, "INSIDECORNER") == 0)
          || (strcmp(rule, "OUTSIDECORNER") == 0)
          || (strcmp(rule, "STEP") == 0))) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "%s ", rule);
    } else {
      fprintf(lefwFile, "%s ", rule);
    }
  }
  if (maxLength) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "LENGTHSUM %.11g ", maxLength);
    } else {
      fprintf(lefwFile, "LENGTHSUM %.11g ", maxLength);
    }
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerRoutingMinstepMaxEdges(double distance, double maxEdges)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   MINSTEP %.11g MAXEDGES %.11g ;\n",
             distance,
             maxEdges);
  } else {
    fprintf(
        lefwFile, "   MINSTEP %.11g MAXEDGES %.11g ;\n", distance, maxEdges);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingProtrusion(double width1, double length, double width2)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;  // only routing calls this func
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   PROTRUSIONWIDTH %.11g LENGTH %.11g WIDTH %.11g ;\n",
             width1,
             length,
             width2);
  } else {
    fprintf(lefwFile,
            "   PROTRUSIONWIDTH %.11g LENGTH %.11g WIDTH %.11g ;\n",
            width1,
            length,
            width2);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingStartSpacingtableParallel(int numLength, double* length)
{
  int i;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRoutingReqData) {
    return LEFW_BAD_ORDER;
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SPACINGTABLE\n");
    encPrint(lefwFile, (char*) "     PARALLELRUNLENGTH");
    for (i = 0; i < numLength; i++) {
      encPrint(lefwFile, (char*) " %.11g", length[i]);
    }
  } else {
    fprintf(lefwFile, "   SPACINGTABLE\n");
    fprintf(lefwFile, "     PARALLELRUNLENGTH");
    for (i = 0; i < numLength; i++) {
      fprintf(lefwFile, " %.11g", length[i]);
    }
  }
  lefwState = LEFW_LAYERROUTING_SP_START;
  lefwLines += 2;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingtableParallelWidth(double width,
                                              int numSpacing,
                                              double* spacing)
{
  int i;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_SP_START
      && lefwState != LEFW_LAYERROUTINGWIDTH) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n       WIDTH %.11g", width);
    for (i = 0; i < numSpacing; i++) {
      encPrint(lefwFile, (char*) " %.11g", spacing[i]);
    }
  } else {
    fprintf(lefwFile, "\n       WIDTH %.11g", width);
    for (i = 0; i < numSpacing; i++) {
      fprintf(lefwFile, " %.11g", spacing[i]);
    }
  }
  lefwState = LEFW_LAYERROUTINGWIDTH;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingStartSpacingtableInfluence()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRoutingReqData) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SPACINGTABLE\n");
    encPrint(lefwFile, (char*) "     INFLUENCE");
  } else {
    fprintf(lefwFile, "   SPACINGTABLE\n");
    fprintf(lefwFile, "     INFLUENCE");
  }
  lefwState = LEFW_LAYERROUTINGWIDTH;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingInfluenceWidth(double width,
                                          double distance,
                                          double spacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTINGWIDTH) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "\n       WIDTH %.11g WITHIN %.11%.11gSPACING %.11g",
             width,
             distance,
             spacing);
  } else {
    fprintf(lefwFile,
            "\n       WIDTH %.11g WITHIN %.11g SPACING %.11g",
            width,
            distance,
            spacing);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingStartSpacingtableTwoWidths()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRoutingReqData) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SPACINGTABLE\n");
    encPrint(lefwFile, (char*) "     TWOWIDTHS");
  } else {
    fprintf(lefwFile, "   SPACINGTABLE\n");
    fprintf(lefwFile, "     TWOWIDTHS");
  }
  lefwState = LEFW_LAYERROUTINGWIDTH;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutingSpacingtableTwoWidthsWidth(double width,
                                               double runLength,
                                               int numSpacing,
                                               double* spacing)
{
  int i;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_SP_START
      && lefwState != LEFW_LAYERROUTINGWIDTH) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n       WIDTH %.11g", width);
    if (runLength) {
      encPrint(lefwFile, (char*) " PRL %.11g", runLength);
    }
    for (i = 0; i < numSpacing; i++) {
      encPrint(lefwFile, (char*) " %.11g", spacing[i]);
    }
  } else {
    fprintf(lefwFile, "\n       WIDTH %.11g", width);
    if (runLength) {
      fprintf(lefwFile, " PRL %.11g", runLength);
    }
    for (i = 0; i < numSpacing; i++) {
      fprintf(lefwFile, " %.11g", spacing[i]);
    }
  }
  lefwState = LEFW_LAYERROUTINGWIDTH;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerRoutineEndSpacingtable()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTINGWIDTH) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) " ;\n");
  } else {
    fprintf(lefwFile, " ;\n");
  }

  lefwLines++;
  lefwState = LEFW_LAYERROUTING;
  return LEFW_OK;
}

int lefwEndLayerRouting(const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRoutingReqData) {
    return LEFW_BAD_ORDER;
  }
  if (prtSemiColon) {
    // the previous statement hasn't written the ; yet
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) ";\n");
    } else {
      fprintf(lefwFile, ";\n");
    }
    prtSemiColon = 0;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", layerName);
  } else {
    fprintf(lefwFile, "END %s\n\n", layerName);
  }

  lefwLines++;
  lefwSynArray[LEFW_LAYERROUTING] = 0;
  lefwState = LEFW_LAYERROUTING_END;
  lefwIsRouting = 0;
  return LEFW_OK;
}

int lefwLayerACCurrentDensity(const char* type, double value)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (strcmp(type, "PEAK") && strcmp(type, "AVERAGE") && strcmp(type, "RMS")) {
    return LEFW_BAD_DATA;  // type is PEAK, AVERAGE & RMS only
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ACCURRENTDENSITY %s", type);
    lefwLines++;
    lefwTableLen = 5;
    if (value) {
      encPrint(lefwFile, (char*) " %.11g ;\n", value);
    }
    // that's it for accurrentdensity
    else {
      encPrint(lefwFile, (char*) "\n");
      // expect to have frequency & tableentries
      lefwOldState = lefwState;  // save the previous state
      lefwState = LEFW_LAYERACCURRENT;
    }
  } else {
    fprintf(lefwFile, "   ACCURRENTDENSITY %s", type);
    lefwLines++;
    lefwTableLen = 5;
    if (value) {
      fprintf(lefwFile, " %.11g ;\n", value);  // that's it for accurrentdensity
    } else {
      fprintf(lefwFile, "\n");   //  expect to have frequency & tableentries
      lefwOldState = lefwState;  // save the previous state
      lefwState = LEFW_LAYERACCURRENT;
    }
  }
  return LEFW_OK;
}

int lefwLayerACFrequency(int numFrequency, double* frequency)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERACCURRENT) {
    return LEFW_BAD_ORDER;
  }

  if (numFrequency <= 0) {
    return LEFW_BAD_DATA;  // frequency are required
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FREQUENCY ");
    for (i = 0; i < numFrequency; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *frequency++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      FREQUENCY ");
    for (i = 0; i < numFrequency; i++) {
      fprintf(lefwFile, "%.11g ", *frequency++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwLayerACWidth(int numWidths, double* widths)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERACCURRENT) {
    return LEFW_BAD_ORDER;
  }

  if (numWidths <= 0) {
    return LEFW_OK;  // width is optional
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      WIDTH ");
    for (i = 0; i < numWidths; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *widths++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      WIDTH ");
    for (i = 0; i < numWidths; i++) {
      fprintf(lefwFile, "%.11g ", *widths++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwTableLen = numWidths;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerACCutarea(int numCutareas, double* cutareas)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERACCURRENT) {
    return LEFW_BAD_ORDER;
  }

  if (numCutareas <= 0) {
    return LEFW_OK;  // cutarea is optional
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      CUTAREA ");
    for (i = 0; i < numCutareas; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *cutareas++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      CUTAREA ");
    for (i = 0; i < numCutareas; i++) {
      fprintf(lefwFile, "%.11g ", *cutareas++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwTableLen = numCutareas;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerACTableEntries(int numEntries, double* entries)
{
  int i;
  int j = 0;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERACCURRENT) {
    return LEFW_BAD_ORDER;
  }

  if (numEntries <= 0) {
    return LEFW_BAD_DATA;  // tableEntries are required
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      TABLEENTRIES\n        ");
    for (i = 0; i < numEntries; i++) {
      if (++j > lefwTableLen) {
        encPrint(lefwFile, (char*) "\n        ");
        j = 1;
      }
      encPrint(lefwFile, (char*) "%.11g ", *entries++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      TABLEENTRIES\n        ");
    for (i = 0; i < numEntries; i++) {
      if (++j > lefwTableLen) {
        fprintf(lefwFile, "\n        ");
        j = 1;
      }
      fprintf(lefwFile, "%.11g ", *entries++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwState = lefwOldState;  // restore the previous state
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerDCCurrentDensity(const char* type, double value)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (strcmp(type, "AVERAGE")) {
    return LEFW_BAD_DATA;  // type is AVERAGE
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DCCURRENTDENSITY %s", type);
    lefwLines++;
    lefwTableLen = 5;
    if (value) {
      encPrint(lefwFile, (char*) " %.11g ;\n", value);
    }
    // that's it for accurrentdensity
    else {
      encPrint(lefwFile, (char*) "\n");
      // expect to have frequency & tableentries
      lefwOldState = lefwState;  // save the previous state
      lefwState = LEFW_LAYERDCCURRENT;
    }
  } else {
    fprintf(lefwFile, "   DCCURRENTDENSITY %s", type);
    lefwLines++;
    lefwTableLen = 5;
    if (value) {
      fprintf(lefwFile, " %.11g ;\n", value);  // that's it for accurrentdensity
    } else {
      fprintf(lefwFile, "\n");   // expect to have frequency & tableentries
      lefwOldState = lefwState;  // save the previous state
      lefwState = LEFW_LAYERDCCURRENT;
    }
  }
  return LEFW_OK;
}

int lefwLayerDCWidth(int numWidths, double* widths)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERDCCURRENT) {
    return LEFW_BAD_ORDER;
  }

  // width is allowed in Layer routing only
  if (lefwOldState != LEFW_LAYER_START && lefwOldState != LEFW_LAYER
      && lefwOldState != LEFW_LAYERROUTING_START
      && lefwOldState != LEFW_LAYERROUTING) {
    return LEFW_BAD_DATA;
  }

  if (numWidths <= 0) {
    return LEFW_BAD_DATA;  // width is required
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      WIDTH ");
    for (i = 0; i < numWidths; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *widths++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      WIDTH ");
    for (i = 0; i < numWidths; i++) {
      fprintf(lefwFile, "%.11g ", *widths++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwTableLen = numWidths;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerDCCutarea(int numCutareas, double* cutareas)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERDCCURRENT) {
    return LEFW_BAD_ORDER;
  }

  // cutarea is allowed in Layer non-routing only
  if (lefwOldState != LEFW_LAYER_START && lefwOldState != LEFW_LAYER
      && lefwOldState != LEFW_LAYERROUTING_START
      && lefwOldState != LEFW_LAYERROUTING) {
    return LEFW_BAD_DATA;
  }

  if (numCutareas <= 0) {
    return LEFW_BAD_DATA;  // cutarea is required
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      CUTAREA ");
    for (i = 0; i < numCutareas; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *cutareas++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      CUTAREA ");
    for (i = 0; i < numCutareas; i++) {
      fprintf(lefwFile, "%.11g ", *cutareas++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwTableLen = numCutareas;
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerDCTableEntries(int numEntries, double* entries)
{
  int i;
  int j = 0;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERDCCURRENT) {
    return LEFW_BAD_ORDER;
  }

  if (numEntries <= 0) {
    return LEFW_BAD_DATA;  // tableEntries are required
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      TABLEENTRIES\n        ");
    for (i = 0; i < numEntries; i++) {
      if (++j > lefwTableLen) {
        encPrint(lefwFile, (char*) "\n        ");
        j = 1;
      }
      encPrint(lefwFile, (char*) "%.11g ", *entries++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      TABLEENTRIES\n        ");
    for (i = 0; i < numEntries; i++) {
      if (++j > lefwTableLen) {
        fprintf(lefwFile, "\n        ");
        j = 1;
      }
      fprintf(lefwFile, "%.11g ", *entries++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwState = lefwOldState;  // restore the previous state
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaModel(const char* oxide)
{
  lefw54Num = LEFW_ANTENNAMODEL;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNAMODEL %s ;\n", oxide);
  } else {
    fprintf(lefwFile, "   ANTENNAMODEL %s ;\n", oxide);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNAAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNAAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNAAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaDiffAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNADIFFAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNADIFFAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNADIFFAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaDiffAreaRatioPwl(int numPwls,
                                     double* diffusions,
                                     double* ratios)
{
  int i;

  lefw54Num = LEFW_ANTENNADIFFAREARATIOPWL;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNADIFFAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      encPrint(lefwFile, (char*) "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    encPrint(lefwFile, (char*) ") ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNADIFFAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      fprintf(lefwFile, "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    fprintf(lefwFile, ") ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaCumAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNACUMAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNACUMAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaCumDiffAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNACUMDIFFAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMDIFFAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNACUMDIFFAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaCumDiffAreaRatioPwl(int numPwls,
                                        double* diffusions,
                                        double* ratios)
{
  int i;

  lefw54Num = LEFW_ANTENNACUMDIFFAREARATIOPWL;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMDIFFAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      encPrint(lefwFile, (char*) "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    encPrint(lefwFile, (char*) ") ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNACUMDIFFAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      fprintf(lefwFile, "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    fprintf(lefwFile, ") ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaAreaFactor(double value, const char* diffUseOnly)
{
  lefw54Num = LEFW_ANTENNAAREAFACTOR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  if ((versionNum < 5.4)
      && (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0)) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNAAREAFACTOR %.11g ", value);
    if (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0) {
      encPrint(lefwFile, (char*) "   DIFFUSEONLY ");
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   ANTENNAAREAFACTOR %.11g ", value);
    if (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0) {
      fprintf(lefwFile, "DIFFUSEONLY ");
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaSideAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNASIDEAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNASIDEAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNASIDEAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaDiffSideAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNADIFFSIDEAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNADIFFSIDEAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNADIFFSIDEAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaDiffSideAreaRatioPwl(int numPwls,
                                         double* diffusions,
                                         double* ratios)
{
  int i;

  lefw54Num = LEFW_ANTENNADIFFSIDEAREARATIOPWL;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNADIFFSIDEAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      encPrint(lefwFile, (char*) "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    encPrint(lefwFile, (char*) ") ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNADIFFSIDEAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      fprintf(lefwFile, "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    fprintf(lefwFile, ") ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaCumSideAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNACUMSIDEAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMSIDEAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNACUMSIDEAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

// 11/25/2002 - bug fix: submitted by Craig Files (cfiles@ftc.agilent.com)
// Renamed from lefwLayerAntennaCumSideDiffAreaRatio to match
// the header
int lefwLayerAntennaCumDiffSideAreaRatio(double value)
{
  lefw54Num = LEFW_ANTENNACUMDIFFSIDEAREARATIO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   ANTENNACUMDIFFSIDEAREARATIO %.11g ;\n", value);
  } else {
    fprintf(lefwFile, "   ANTENNACUMDIFFSIDEAREARATIO %.11g ;\n", value);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaCumDiffSideAreaRatioPwl(int numPwls,
                                            double* diffusions,
                                            double* ratios)
{
  int i;

  lefw54Num = LEFW_ANTENNACUMDIFFSIDEAREARATIOPWL;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing or cut calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMDIFFSIDEAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      encPrint(lefwFile, (char*) "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    encPrint(lefwFile, (char*) ") ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNACUMDIFFSIDEAREARATIO PWL ( ");
    for (i = 0; i < numPwls; i++) {
      fprintf(lefwFile, "( %.11g %.11g ) ", *diffusions++, *ratios++);
    }
    fprintf(lefwFile, ") ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwLayerAntennaSideAreaFactor(double value, const char* diffUseOnly)
{
  lefw54Num = LEFW_ANTENNASIDEAREAFACTOR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING) {
    return LEFW_BAD_ORDER;
  }
  // only routing calls this func
  if (!lefwIsRouting) {
    return LEFW_BAD_DATA;
  }
  if ((versionNum < 5.4)
      && (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0)) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNASIDEAREAFACTOR %.11g ", value);
    if (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0) {
      encPrint(lefwFile, (char*) "   DIFFUSEONLY ");
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   ANTENNASIDEAREAFACTOR %.11g ", value);
    if (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0) {
      fprintf(lefwFile, "DIFFUSEONLY ");
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerAntennaCumRoutingPlusCut()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  /* WANDA
    if ((versionNum < 5.4) &&
        (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0))
       return LEFW_WRONG_VERSION;
  */
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNACUMROUTINGPLUSCUT ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNACUMROUTINGPLUSCUT ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerAntennaGatePlusDiff(double plusDiffFactor)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  /* WANDA
    if ((versionNum < 5.4) &&
        (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0))
       return LEFW_WRONG_VERSION;
  */
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   ANTENNAGATEPLUSDIFF %.11g ;\n", plusDiffFactor);
  } else {
    fprintf(lefwFile, "   ANTENNAGATEPLUSDIFF %.11g ;\n", plusDiffFactor);
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerAntennaAreaMinusDiff(double minusDiffFactor)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  /* WANDA
    if ((versionNum < 5.4) &&
        (diffUseOnly && strcmp(diffUseOnly, "DIFFUSEONLY") == 0))
       return LEFW_WRONG_VERSION;
  */
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   ANTENNAAREAMINUSDIFF %.11g ;\n", minusDiffFactor);
  } else {
    fprintf(lefwFile, "   ANTENNAAREAMINUSDIFF %.11g ;\n", minusDiffFactor);
  }
  lefwLines++;
  return LEFW_OK;
}

// 5.7
int lefwLayerAntennaAreaDiffReducePwl(int numPwls,
                                      double* diffAreas,
                                      double* metalDiffFactors)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_LAYERROUTING_START && lefwState != LEFW_LAYERROUTING
      && lefwState != LEFW_LAYER_START && lefwState != LEFW_LAYER) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsRouting && !lefwIsCut) {
    return LEFW_BAD_DATA;
  }
  /* WANDA
    if (versionNum < 5.4)
       return LEFW_WRONG_VERSION;
  */
  if (numPwls < 2) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ANTENNAAREADIFFREDUCEPWL ( ");
    for (i = 0; i < numPwls; i++) {
      encPrint(lefwFile,
               (char*) "( %.11g %.11g ) ",
               *diffAreas++,
               *metalDiffFactors++);
    }
    encPrint(lefwFile, (char*) ") ;\n");
  } else {
    fprintf(lefwFile, "   ANTENNAAREADIFFREDUCEPWL ( ");
    for (i = 0; i < numPwls; i++) {
      fprintf(lefwFile, "( %.11g %.11g ) ", *diffAreas++, *metalDiffFactors++);
    }
    fprintf(lefwFile, ") ;\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwMinimumDensity(double minDensity)
{
  lefw54Num = LEFW_MINIMUMDENSITY;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINIMUMDENSITY %.11g ;\n", minDensity);
  } else {
    fprintf(lefwFile, "   MINIMUMDENSITY %.11g ;\n", minDensity);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwMaximumDensity(double maxDensity)
{
  lefw54Num = LEFW_MAXIMUMDENSITY;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MAXIMUMDENSITY %.11g ;\n", maxDensity);
  } else {
    fprintf(lefwFile, "   MAXIMUMDENSITY %.11g ;\n", maxDensity);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwDensityCheckWindow(double checkWindowLength, double checkWindowWidth)
{
  lefw54Num = LEFW_DENSITYCHECKWINDOW;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   DENSITYCHECKWINDOW %.11g %.11g ;\n",
             checkWindowLength,
             checkWindowWidth);
  } else {
    fprintf(lefwFile,
            "   DENSITYCHECKWINDOW %.11g %.11g ;\n",
            checkWindowLength,
            checkWindowWidth);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwDensityCheckStep(double checkStepValue)
{
  lefw54Num = LEFW_DENSITYCHECKSTEP;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DENSITYCHECKSTEP %.11g ;\n", checkStepValue);
  } else {
    fprintf(lefwFile, "   DENSITYCHECKSTEP %.11g ;\n", checkStepValue);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwFillActiveSpacing(double fillToActiveSpacing)
{
  lefw54Num = LEFW_FILLACTIVESPACING;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   FILLACTIVESPACING %.11g ;\n",
             fillToActiveSpacing);
  } else {
    fprintf(lefwFile, "   FILLACTIVESPACING %.11g ;\n", fillToActiveSpacing);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwMaxviastack(int value, const char* bottomLayer, const char* topLayer)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsMaxviastack) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "MAXVIASTACK %d ", value);
    if (bottomLayer) {
      encPrint(lefwFile, (char*) "RANGE %s %s ;\n", bottomLayer, topLayer);
    } else {
      encPrint(lefwFile, (char*) ";\n");
    }
  } else {
    fprintf(lefwFile, "MAXVIASTACK %d ", value);
    if (bottomLayer) {
      fprintf(lefwFile, "RANGE %s %s ;\n", bottomLayer, topLayer);
    } else {
      fprintf(lefwFile, ";\n");
    }
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwStartPropDef()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwSynArray[LEFW_PROPERTYDEF_START]) {
    return LEFW_ALREADY_DEFINED;
  }
  lefwSynArray[LEFW_ANTENNASIZE] = 1;
  if (lefwState == LEFW_PROPERTYDEF_START || lefwState == LEFW_PROPERTYDEF) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "PROPERTYDEFINITIONS\n");
  } else {
    fprintf(lefwFile, "PROPERTYDEFINITIONS\n");
  }

  lefwLines++;
  lefwState = LEFW_PROPERTYDEF_START;
  lefwSynArray[LEFW_PROPERTYDEF_START] = 1;
  return LEFW_OK;
}

int lefwIntPropDef(const char* objType,
                   const char* propName,
                   double leftRange,
                   double rightRange,  // optional
                   int propValue       // optional
)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_PROPERTYDEF_START && lefwState != LEFW_PROPERTYDEF) {
    return LEFW_BAD_ORDER;
  }
  /*
    if ((! objType && ! *objType) || (! propName && ! *propName))
  */
  if (((objType == nullptr) || (*objType == 0))
      || ((propName == nullptr) || (*propName == 0))) {
    return LEFW_BAD_DATA;
  }

  if (strcmp(objType, "LIBRARY") && strcmp(objType, "VIA")
      && strcmp(objType, "MACRO") && strcmp(objType, "PIN")
      && strcmp(objType, "LAYER") && strcmp(objType, "NONDEFAULTRULE")
      && strcmp(objType, "VIARULE")) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   %s %s INTEGER ", objType, propName);
    if (leftRange || rightRange) {
      encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      encPrint(lefwFile, (char*) "%d ", propValue);
    }

    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   %s %s INTEGER ", objType, propName);
    if (leftRange || rightRange) {
      fprintf(lefwFile, "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      fprintf(lefwFile, "%d ", propValue);
    }

    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_PROPERTYDEF;
  return LEFW_OK;
}

int lefwRealPropDef(const char* objType,
                    const char* propName,
                    double leftRange,
                    double rightRange,  // optional
                    double propValue    // optional
)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_PROPERTYDEF_START && lefwState != LEFW_PROPERTYDEF) {
    return LEFW_BAD_ORDER;
  }
  if (((objType == nullptr) || (*objType == 0))
      || ((propName == nullptr) || (*propName == 0))) {  // require
    return LEFW_BAD_DATA;
  }

  if (strcmp(objType, "LIBRARY") && strcmp(objType, "VIA")
      && strcmp(objType, "MACRO") && strcmp(objType, "PIN")
      && strcmp(objType, "LAYER") && strcmp(objType, "NONDEFAULTRULE")
      && strcmp(objType, "VIARULE")) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   %s %s REAL ", objType, propName);
    if (leftRange || rightRange) {
      encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      encPrint(lefwFile, (char*) "%.11g ", propValue);
    }

    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   %s %s REAL ", objType, propName);
    if (leftRange || rightRange) {
      fprintf(lefwFile, "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      fprintf(lefwFile, "%.11g ", propValue);
    }

    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_PROPERTYDEF;
  return LEFW_OK;
}

int lefwStringPropDef(const char* objType,
                      const char* propName,
                      double leftRange,
                      double rightRange,     // optional
                      const char* propValue  // optional
)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_PROPERTYDEF_START && lefwState != LEFW_PROPERTYDEF) {
    return LEFW_BAD_ORDER;
  }
  if (((objType == nullptr) || (*objType == 0))
      || ((propName == nullptr) || (*propName == 0))) {
    return LEFW_BAD_DATA;
  }

  if (strcmp(objType, "LIBRARY") && strcmp(objType, "VIA")
      && strcmp(objType, "MACRO") && strcmp(objType, "PIN")
      && strcmp(objType, "LAYER") && strcmp(objType, "NONDEFAULTRULE")
      && strcmp(objType, "VIARULE")) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   %s %s STRING ", objType, propName);
    if (leftRange || rightRange) {
      encPrint(lefwFile, (char*) "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      encPrint(lefwFile, (char*) "\"%s\" ", propValue);  // string, set quotes
    }

    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   %s %s STRING ", objType, propName);
    if (leftRange || rightRange) {
      fprintf(lefwFile, "RANGE %.11g %.11g ", leftRange, rightRange);
    }

    if (propValue) {
      fprintf(lefwFile, "\"%s\" ", propValue);  // string, set quotes
    }

    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_PROPERTYDEF;
  return LEFW_OK;
}

int lefwEndPropDef()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_PROPERTYDEF_START && lefwState != LEFW_PROPERTYDEF) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END PROPERTYDEFINITIONS\n\n");
  } else {
    fprintf(lefwFile, "END PROPERTYDEFINITIONS\n\n");
  }
  lefwLines++;
  lefwState = LEFW_PROPERTYDEF_END;
  return LEFW_OK;
}

int lefwEnd()
{
  if (!lefwFile) {
    return 1;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END LIBRARY\n");
  } else {
    fprintf(lefwFile, "END LIBRARY\n");
  }
  lefwLines++;
  // lefwFile = 0;
  lefwState = LEFW_DONE;
  return LEFW_OK;
}

int lefwStartVia(const char* viaName, const char* isDefault)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_VIA_START || lefwState == LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END
      && (!lefwIsNonDefaultRule)) {  // via defined in nondefaultrule
    return LEFW_BAD_ORDER;           // not of the ENDs
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "VIA %s ", viaName);
    if (isDefault && strcmp(isDefault, "DEFAULT") == 0) {
      encPrint(lefwFile, (char*) "DEFAULT");
    }
    encPrint(lefwFile, (char*) "\n");
  } else {
    fprintf(lefwFile, "VIA %s ", viaName);
    if (isDefault && strcmp(isDefault, "DEFAULT") == 0) {
      fprintf(lefwFile, "DEFAULT");
    }
    fprintf(lefwFile, "\n");
  }
  lefwLines++;

  lefwSynArray[LEFW_VIA_START] = 1;
  lefwState = LEFW_VIA_START;
  lefwDidLayer = 0;  // hasn't set the layer yet
  lefwViaHasVal = 0;
  return LEFW_OK;
}

int lefwViaTopofstackonly()
{
  lefwObsoleteNum = LEFW_VIATOPOFSTACKONLY;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   TOPOFSTACKONLY\n");
  } else {
    fprintf(lefwFile, "   TOPOFSTACKONLY\n");
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwViaForeign(const char* foreignName,
                   double xl,  // optional
                   double yl,  // optional
                   int orient)
{  // optional
  lefwObsoleteNum = LEFW_VIAFOREIGN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FOREIGN %s ", foreignName);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0 0 for pt
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   FOREIGN %s ", foreignName);
    if (xl || yl) {
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        fprintf(lefwFile, "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0 0 for pt
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", lefwOrient(orient));
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_VIA;
  return LEFW_OK;
}

int lefwViaForeignStr(const char* foreignName,
                      double xl,  // optional
                      double yl,  // optional
                      const char* orient)
{  // optional
  lefwObsoleteNum = LEFW_VIAFOREIGN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FOREIGN %s ", foreignName);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        encPrint(lefwFile, (char*) "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0 0 for pt
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", orient);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   FOREIGN %s ", foreignName);
    if (xl || yl) {
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        fprintf(lefwFile, "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0 0 for pt
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", orient);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_VIA;
  return LEFW_OK;
}

int lefwViaResistance(double resistance)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }

  if (lefwViaHasVal) {
    return LEFW_ALREADY_DEFINED;  // either Resistance or
  }
  // ViaRule has defined
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   RESISTANCE %.11g ;\n", resistance);
  } else {
    fprintf(lefwFile, "   RESISTANCE %.11g ;\n", resistance);
  }

  lefwLines++;
  lefwState = LEFW_VIA;
  lefwViaHasVal = 1;
  return LEFW_OK;
}

int lefwViaLayer(const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LAYER %s ;\n", layerName);
  } else {
    fprintf(lefwFile, "   LAYER %s ;\n", layerName);
  }

  lefwLines++;
  lefwState = LEFW_VIA;
  lefwDidLayer = 1;
  return LEFW_OK;
}

int lefwViaLayerRect(double x1l, double y1l, double x2l, double y2l, int mask)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwDidLayer) {
    return LEFW_BAD_ORDER;
  }

  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (mask) {
      encPrint(lefwFile,
               (char*) "      RECT MASK %d %.11g %.11g %.11g %.11g ;\n",
               mask,
               x1l,
               y1l,
               x2l,
               y2l);
    } else {
      encPrint(lefwFile,
               (char*) "      RECT %.11g %.11g %.11g %.11g ;\n",
               x1l,
               y1l,
               x2l,
               y2l);
    }
  } else {
    if (mask) {
      fprintf(lefwFile,
              "      RECT MASK %d %.11g %.11g %.11g %.11g ;\n",
              mask,
              x1l,
              y1l,
              x2l,
              y2l);
    } else {
      fprintf(lefwFile,
              "      RECT %.11g %.11g %.11g %.11g ;\n",
              x1l,
              y1l,
              x2l,
              y2l);
    }
  }

  lefwLines++;
  lefwState = LEFW_VIA;
  return LEFW_OK;
}

int lefwViaLayerPolygon(int num_polys, double* xl, double* yl, int mask)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwDidLayer) {
    return LEFW_BAD_ORDER;
  }
  if (num_polys < 4) {
    return LEFW_BAD_DATA;
  }

  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (mask) {
      encPrint(lefwFile, (char*) "      POLYGON MASK %d ", mask);
    } else {
      encPrint(lefwFile, (char*) "      POLYGON ");
    }
    for (i = 0; i < num_polys; i++) {
      if (i == 0) {
        encPrint(lefwFile, (char*) "%.11g %.11g ", *xl++, *yl++);
      } else {
        if ((i % 5) == 0) {
          encPrint(
              lefwFile, (char*) "\n              %.11g %.11g", *xl++, *yl++);
          lefwLines++;
        } else {
          encPrint(lefwFile, (char*) "%.11g %.11g ", *xl++, *yl++);
        }
      }
    }
    encPrint(lefwFile, (char*) " ;\n");
  } else {
    if (mask) {
      fprintf(lefwFile, "      POLYGON MASK %d ", mask);
    } else {
      fprintf(lefwFile, "      POLYGON ");
    }
    for (i = 0; i < num_polys; i++) {
      if (i == 0) {
        fprintf(lefwFile, "%.11g %.11g", *xl++, *yl++);
      } else {
        if ((i % 5) == 0) {
          fprintf(lefwFile, "\n              %.11g %.11g", *xl++, *yl++);
          lefwLines++;
        } else {
          fprintf(lefwFile, "%.11g %.11g ", *xl++, *yl++);
        }
      }
    }
    fprintf(lefwFile, " ;\n");
  }
  lefwLines++;
  lefwState = LEFW_VIA;
  return LEFW_OK;
}

int lefwViaViarule(const char* viaRuleName,
                   double xCutSize,
                   double yCutSize,
                   const char* botMetalLayer,
                   const char* cutLayer,
                   const char* topMetalLayer,
                   double xCutSpacing,
                   double yCutSpacing,
                   double xBotEnc,
                   double yBotEnc,
                   double xTopEnc,
                   double yTopEnc)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }

  if (lefwViaHasVal) {
    return LEFW_ALREADY_DEFINED;  // either Resistance or
  }
  // ViaRule has defined
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   VIARULE %s ;\n", viaRuleName);
    encPrint(
        lefwFile, (char*) "     CUTSIZE %.11g %.11g ;\n", xCutSize, yCutSize);
    encPrint(lefwFile,
             (char*) "     LAYERS %s %s %s ;\n",
             botMetalLayer,
             cutLayer,
             topMetalLayer);
    encPrint(lefwFile,
             (char*) "     CUTSPACING %.11g %.11g ;\n",
             xCutSpacing,
             yCutSpacing);
    encPrint(lefwFile,
             (char*) "     ENCLOSURE %.11g %.11g %.11g %.11g ;\n",
             xBotEnc,
             yBotEnc,
             xTopEnc,
             yTopEnc);
  } else {
    fprintf(lefwFile, "   VIARULE %s ;\n", viaRuleName);
    fprintf(lefwFile, "     CUTSIZE %.11g %.11g ;\n", xCutSize, yCutSize);
    fprintf(lefwFile,
            "     LAYERS %s %s %s ;\n",
            botMetalLayer,
            cutLayer,
            topMetalLayer);
    fprintf(
        lefwFile, "     CUTSPACING %.11g %.11g ;\n", xCutSpacing, yCutSpacing);
    fprintf(lefwFile,
            "     ENCLOSURE %.11g %.11g %.11g %.11g ;\n",
            xBotEnc,
            yBotEnc,
            xTopEnc,
            yTopEnc);
  }
  lefwLines++;
  lefwState = LEFW_VIAVIARULE;
  lefwViaHasVal = 1;
  return LEFW_OK;
}

int lefwViaViaruleRowCol(int numCutRows, int numCutCols)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIAVIARULE) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "     ROWCOL %d %d ;\n", numCutRows, numCutCols);
  } else {
    fprintf(lefwFile, "     ROWCOL %d %d ;\n", numCutRows, numCutCols);
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwViaViaruleOrigin(double xOffset, double yOffset)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIAVIARULE) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "     ORIGIN %.11g %.11g ;\n", xOffset, yOffset);
  } else {
    fprintf(lefwFile, "     ORIGIN %.11g %.11g ;\n", xOffset, yOffset);
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwViaViaruleOffset(double xBotOffset,
                         double yBotOffset,
                         double xTopOffset,
                         double yTopOffset)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIAVIARULE) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "     OFFSET %.11g %.11g %.11g %.11g ;\n",
             xBotOffset,
             yBotOffset,
             xTopOffset,
             yTopOffset);
  } else {
    fprintf(lefwFile,
            "     OFFSET %.11g %.11g %.11g %.11g ;\n",
            xBotOffset,
            yBotOffset,
            xTopOffset,
            yTopOffset);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwViaViarulePattern(const char* cutPattern)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIAVIARULE) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "     PATTERN %s ;\n", cutPattern);
  } else {
    fprintf(lefwFile, "     PATTERN %s ;\n", cutPattern);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwStringProperty(const char* propName, const char* propValue)
{
  if ((lefwState != LEFW_VIA) && (lefwState != LEFW_LAYER)
      && (lefwState != LEFW_VIARULE) && (lefwState != LEFW_MACRO_START)
      && (lefwState != LEFW_MACRO) && (lefwState != LEFW_VIA_START)
      && (lefwState != LEFW_VIARULE_START) && (lefwState != LEFW_LAYER_START)
      && (lefwState != LEFW_BEGINEXT) && (lefwState != LEFW_VIAVIARULE)
      && (lefwState != LEFW_LAYERROUTING_START)
      && (lefwState != LEFW_LAYERROUTING)) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "   PROPERTY %s \"%s\" ;\n", propName, propValue);
  } else {
    fprintf(lefwFile, "   PROPERTY %s \"%s\" ;\n", propName, propValue);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwRealProperty(const char* propName, double propValue)
{
  if ((lefwState != LEFW_VIA) && (lefwState != LEFW_LAYER)
      && (lefwState != LEFW_VIARULE) && (lefwState != LEFW_MACRO_START)
      && (lefwState != LEFW_MACRO) && (lefwState != LEFW_VIA_START)
      && (lefwState != LEFW_VIARULE_START) && (lefwState != LEFW_LAYER_START)
      && (lefwState != LEFW_BEGINEXT) && (lefwState != LEFW_VIAVIARULE)) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   PROPERTY %s %.11g ;\n", propName, propValue);
  } else {
    fprintf(lefwFile, "   PROPERTY %s %.11g ;\n", propName, propValue);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwIntProperty(const char* propName, int propValue)
{
  if ((lefwState != LEFW_VIA) && (lefwState != LEFW_LAYER)
      && (lefwState != LEFW_VIARULE) && (lefwState != LEFW_MACRO_START)
      && (lefwState != LEFW_MACRO) && (lefwState != LEFW_VIA_START)
      && (lefwState != LEFW_VIARULE_START) && (lefwState != LEFW_LAYER_START)
      && (lefwState != LEFW_BEGINEXT) && (lefwState != LEFW_VIAVIARULE)) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   PROPERTY %s %d ;\n", propName, propValue);
  } else {
    fprintf(lefwFile, "   PROPERTY %s %d ;\n", propName, propValue);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwEndVia(const char* viaName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA
      && lefwState != LEFW_VIAVIARULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", viaName);
  } else {
    fprintf(lefwFile, "END %s\n\n", viaName);
  }

  lefwLines++;
  lefwState = LEFW_VIA_END;
  lefwDidLayer = 0;
  return LEFW_OK;
}

// internal function
int lefwViaRulePrtLayer(const char* layerName,
                        const char* direction,
                        double minWidth,
                        double maxWidth,
                        double overhang,
                        double metalOverhang)
{
  lefwObsoleteNum = LEFW_VIARULEGENERATE;
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LAYER %s ;\n", layerName);
  } else {
    fprintf(lefwFile, "   LAYER %s ;\n", layerName);
  }
  if (direction && strcmp(direction, "HORIZONTAL")
      && strcmp(direction, "VERTICAL")) {
    return LEFW_BAD_DATA;
  }
  if (versionNum >= 5.6 && (direction || overhang || metalOverhang)) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    if (direction) {
      encPrint(lefwFile, (char*) "      DIRECTION %s ;\n", direction);
      lefwLines = lefwLines + 2;
    } else {
      lefwLines++;
    }
    if (minWidth || maxWidth) {
      encPrint(lefwFile,
               (char*) "      WIDTH %.11g TO %.11g ;\n",
               minWidth,
               maxWidth);
      lefwLines++;
    }
    if (overhang) {
      encPrint(lefwFile, (char*) "      OVERHANG %.11g ;\n", overhang);
      lefwLines++;
    }
    if (metalOverhang) {
      encPrint(
          lefwFile, (char*) "      METALOVERHANG %.11g ;\n", metalOverhang);
      lefwLines++;
    }
  } else {
    if (direction) {
      fprintf(lefwFile, "      DIRECTION %s ;\n", direction);
      lefwLines = lefwLines + 2;
    } else {
      lefwLines++;
    }
    if (minWidth || maxWidth) {
      fprintf(lefwFile, "      WIDTH %.11g TO %.11g ;\n", minWidth, maxWidth);
      lefwLines++;
    }
    if (overhang) {
      fprintf(lefwFile, "      OVERHANG %.11g ;\n", overhang);
      lefwLines++;
    }
    if (metalOverhang) {
      fprintf(lefwFile, "      METALOVERHANG %.11g ;\n", metalOverhang);
      lefwLines++;
    }
  }
  return LEFW_OK;
}

int lefwStartViaRule(const char* viaRuleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_VIARULE_START || lefwState == LEFW_VIARULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }

  if (!viaRuleName || viaRuleName == nullptr || *viaRuleName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "VIARULE %s\n", viaRuleName);
  } else {
    fprintf(lefwFile, "VIARULE %s\n", viaRuleName);
  }
  lefwLines++;

  lefwSynArray[LEFW_VIARULE_START] = 1;
  lefwState = LEFW_VIARULE_START;
  lefwDidLayer = 0;  // hasn't set the layer yet
  lefwNumViaRuleLayers = 0;
  return LEFW_OK;
}

int lefwViaRuleLayer(const char* layerName,
                     const char* direction,
                     double minWidth,
                     double maxWidth,  // optional
                     double overhang,
                     double metalOverhang)
{  // optional
  int status;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULE_START && lefwState != LEFW_VIARULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwNumViaRuleLayers >= 2) {
    return LEFW_BAD_ORDER;
  }
  if ((status = lefwViaRulePrtLayer(
           layerName, direction, minWidth, maxWidth, overhang, metalOverhang))
      != LEFW_OK) {
    return status;
  }
  lefwNumViaRuleLayers++;
  lefwState = LEFW_VIARULE;
  return LEFW_OK;
}

int lefwViaRuleVia(const char* viaName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwNumViaRuleLayers != 2) {  // this routine has to be after two layers
    return LEFW_BAD_ORDER;          // be written
  }
  if (!viaName || !*viaName) {  // viaName is required
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      VIA %s ;\n", viaName);
  } else {
    fprintf(lefwFile, "      VIA %s ;\n", viaName);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwEndViaRule(const char* viaRuleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIARULE_START && lefwState != LEFW_VIARULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", viaRuleName);
  } else {
    fprintf(lefwFile, "END %s\n\n", viaRuleName);
  }

  lefwLines++;
  lefwState = LEFW_VIARULE_END;
  lefwDidLayer = 0;
  lefwNumViaRuleLayers = 0;
  return LEFW_OK;
}

int lefwStartViaRuleGen(const char* viaRuleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_VIARULEGEN_START || lefwState == LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }

  if (!viaRuleName || viaRuleName == nullptr || *viaRuleName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "VIARULE %s GENERATE", viaRuleName);
  } else {
    fprintf(lefwFile, "VIARULE %s GENERATE", viaRuleName);
  }
  lefwLines++;

  lefwSynArray[LEFW_VIARULEGEN_START] = 1;
  lefwState = LEFW_VIARULEGEN_START;
  lefwDidLayer = 0;  // hasn't set the layer yet
  lefwNumViaRuleLayers = 0;
  return LEFW_OK;
}

int lefwViaRuleGenDefault()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULEGEN_START && lefwState != LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) " DEFAULT");
  } else {
    fprintf(lefwFile, " DEFAULT");
  }
  return LEFW_OK;
}

int lefwViaRuleGenLayer(const char* layerName,
                        const char* direction,
                        double minWidth,
                        double maxWidth,  // optional
                        double overhang,
                        double metalOverhang)
{  // optional
  int status;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULEGEN_START && lefwState != LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwNumViaRuleLayers >= 2) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {              // add a new line since, lefwViaRuleGen
    encPrint(lefwFile, (char*) "\n");  // & lefwViaRuleGenDefault do not
  } else {
    fprintf(lefwFile, "\n");
  }
  if ((status = lefwViaRulePrtLayer(
           layerName, direction, minWidth, maxWidth, overhang, metalOverhang))
      != LEFW_OK) {
    return status;
  }
  lefwNumViaRuleLayers++;
  lefwState = LEFW_VIARULEGEN;
  return LEFW_OK;
}

int lefwViaRuleGenLayerEnclosure(const char* layerName,
                                 double overhang1,
                                 double overhang2,
                                 double minWidth,
                                 double maxWidth)
{  // optional

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULEGEN_START && lefwState != LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwNumViaRuleLayers >= 2) {
    return LEFW_BAD_ORDER;
  }

  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n   LAYER %s ;\n", layerName);
  } else {
    fprintf(lefwFile, "\n   LAYER %s ;\n", layerName);
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "      ENCLOSURE %.11g %.11g ;\n",
             overhang1,
             overhang2);
    lefwLines = lefwLines + 2;
    if (minWidth || maxWidth) {
      encPrint(lefwFile,
               (char*) "      WIDTH %.11g TO %.11g ;\n",
               minWidth,
               maxWidth);
      lefwLines++;
    }
  } else {
    fprintf(lefwFile, "      ENCLOSURE %.11g %.11g ;\n", overhang1, overhang2);
    lefwLines = lefwLines + 2;
    if (minWidth || maxWidth) {
      fprintf(lefwFile, "      WIDTH %.11g TO %.11g ;\n", minWidth, maxWidth);
      lefwLines++;
    }
  }

  lefwNumViaRuleLayers++;
  lefwState = LEFW_VIARULEGEN;
  return LEFW_OK;
}

int lefwViaRuleGenLayer3(const char* layerName,
                         double xl,
                         double yl,
                         double xh,
                         double yh,
                         double xSpacing,
                         double ySpacing,
                         double resistance)
{  // optional

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwNumViaRuleLayers != 2) {  // this routine has to be after two layers
    return LEFW_BAD_ORDER;          // be written
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LAYER %s ;\n", layerName);
    encPrint(lefwFile,
             (char*) "      RECT %.11g %.11g %.11g %.11g ;\n",
             xl,
             yl,
             xh,
             yh);
    encPrint(lefwFile,
             (char*) "      SPACING %.11g BY %.11g ;\n",
             xSpacing,
             ySpacing);
    if (resistance) {
      encPrint(lefwFile, (char*) "      RESISTANCE %.11g ;\n", resistance);
      lefwLines++;
    }
  } else {
    fprintf(lefwFile, "   LAYER %s ;\n", layerName);
    fprintf(lefwFile, "      RECT %.11g %.11g %.11g %.11g ;\n", xl, yl, xh, yh);
    fprintf(lefwFile, "      SPACING %.11g BY %.11g ;\n", xSpacing, ySpacing);
    if (resistance) {
      fprintf(lefwFile, "      RESISTANCE %.11g ;\n", resistance);
      lefwLines++;
    }
  }
  lefwLines += 3;
  return LEFW_OK;
}

int lefwEndViaRuleGen(const char* viaRuleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIARULEGEN_START && lefwState != LEFW_VIARULEGEN) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", viaRuleName);
  } else {
    fprintf(lefwFile, "END %s\n\n", viaRuleName);
  }

  lefwLines++;
  lefwState = LEFW_VIARULEGEN_END;
  lefwDidLayer = 0;
  lefwNumViaRuleLayers = 0;
  return LEFW_OK;
}

int lefwStartNonDefaultRule(const char* ruleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_NONDEFAULTRULE_START
      || lefwState == LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }

  if (!ruleName || ruleName == nullptr || *ruleName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "NONDEFAULTRULE %s\n", ruleName);
  } else {
    fprintf(lefwFile, "NONDEFAULTRULE %s\n", ruleName);
  }
  lefwLines++;

  lefwSynArray[LEFW_NONDEFAULTRULE_START] = 1;
  lefwState = LEFW_NONDEFAULTRULE_START;
  lefwDidLayer = 0;  // hasn't set the layer yet
  lefwIsNonDefaultRule = 1;
  return LEFW_OK;
}

int lefwNonDefaultRuleHardspacing()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START
      && lefwState != LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   HARDSPACING ;\n");
  } else {
    fprintf(lefwFile, "   HARDSPACING ;\n");
  }
  return LEFW_OK;
}

int lefwNonDefaultRuleStartVia(const char* viaName, const char* isDefault)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_VIA_START || lefwState == LEFW_VIA
      || (lefwState != LEFW_NONDEFAULTRULE_START
          && lefwState != LEFW_NONDEFAULTRULE)) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   VIA %s ", viaName);
    if (isDefault && strcmp(isDefault, "DEFAULT") == 0) {
      encPrint(lefwFile, (char*) "DEFAULT");
    }
    encPrint(lefwFile, (char*) "\n");
  } else {
    fprintf(lefwFile, "   VIA %s ", viaName);
    if (isDefault && strcmp(isDefault, "DEFAULT") == 0) {
      fprintf(lefwFile, "DEFAULT");
    }
    fprintf(lefwFile, "\n");
  }
  lefwLines++;
  lefwViaHasVal = 0;

  lefwSynArray[LEFW_VIA_START] = 1;
  lefwState = LEFW_VIA_START;
  lefwDidLayer = 0;  // hasn't set the layer yet
  return LEFW_OK;
}

int lefwNonDefaultRuleEndVia(const char* viaName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_VIA_START && lefwState != LEFW_VIA) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END %s\n\n", viaName);
  } else {
    fprintf(lefwFile, "   END %s\n\n", viaName);
  }

  lefwLines++;
  lefwState = LEFW_NONDEFAULTRULE;
  lefwDidLayer = 0;
  return LEFW_OK;
}

int lefwNonDefaultRuleUseVia(const char* viaName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START
      && lefwState != LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   USEVIA %s ;\n", viaName);
  } else {
    fprintf(lefwFile, "   USEVIA %s ;\n", viaName);
  }
  return LEFW_OK;
}

int lefwNonDefaultRuleUseViaRule(const char* viaRuleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START
      && lefwState != LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   USEVIARULE %s ;\n", viaRuleName);
  } else {
    fprintf(lefwFile, "   USEVIARULE %s ;\n", viaRuleName);
  }
  return LEFW_OK;
}

int lefwNonDefaultRuleMinCuts(const char* layerName, int numCuts)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START
      && lefwState != LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   MINCUTS %s %d ;\n", layerName, numCuts);
  } else {
    fprintf(lefwFile, "   MINCUTS %s %d ;\n", layerName, numCuts);
  }
  return LEFW_OK;
}

int lefwNonDefaultRuleLayer(const char* routingLayerName,
                            double width,
                            double minSpacing,
                            double wireExtension,
                            double resist,
                            double capacitance,
                            double edgeCap)
{
  lefwObsoleteNum = LEFW_NONDEFAULTRULELAYER;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START
      && lefwState != LEFW_NONDEFAULTRULE) {
    return LEFW_BAD_ORDER;
  }
  if (!routingLayerName || routingLayerName == nullptr
      || *routingLayerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (versionNum >= 5.6 && (resist || capacitance || edgeCap)) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LAYER %s\n", routingLayerName);
    encPrint(lefwFile, (char*) "      WIDTH %.11g ;\n", width);
    encPrint(lefwFile, (char*) "      SPACING %.11g ;\n", minSpacing);
    if (wireExtension) {
      encPrint(
          lefwFile, (char*) "      WIREEXTENSION %.11g ;\n", wireExtension);
      lefwLines++;
    }
    if (resist) {
      encPrint(lefwFile, (char*) "      RESISTANCE RPERSQ %.11g ;\n", resist);
      lefwLines++;
    }
    if (capacitance) {
      encPrint(lefwFile,
               (char*) "      CAPACITANCE CPERSQDIST %.11g ;\n",
               capacitance);
      lefwLines++;
    }
    if (edgeCap) {
      encPrint(lefwFile, (char*) "      EDGECAPACITANCE %.11g ;\n", edgeCap);
      lefwLines++;
    }
    encPrint(lefwFile, (char*) "   END %s\n\n", routingLayerName);
  } else {
    fprintf(lefwFile, "   LAYER %s\n", routingLayerName);
    fprintf(lefwFile, "      WIDTH %.11g ;\n", width);
    fprintf(lefwFile, "      SPACING %.11g ;\n", minSpacing);
    if (wireExtension) {
      fprintf(lefwFile, "      WIREEXTENSION %.11g ;\n", wireExtension);
      lefwLines++;
    }
    if (resist) {
      fprintf(lefwFile, "      RESISTANCE RPERSQ %.11g ;\n", resist);
      lefwLines++;
    }
    if (capacitance) {
      fprintf(lefwFile, "      CAPACITANCE CPERSQDIST %.11g ;\n", capacitance);
      lefwLines++;
    }
    if (edgeCap) {
      fprintf(lefwFile, "      EDGECAPACITANCE %.11g ;\n", edgeCap);
      lefwLines++;
    }
    fprintf(lefwFile, "   END %s\n\n", routingLayerName);
  }

  lefwLines = lefwLines + 4;
  lefwSynArray[LEFW_NONDEFAULTRULE] = 1;
  lefwState = LEFW_NONDEFAULTRULE;
  return LEFW_OK;
}

int lefwEndNonDefaultRule(const char* ruleName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_NONDEFAULTRULE_START && lefwState != LEFW_NONDEFAULTRULE
      && lefwState != LEFW_VIA_END && lefwState != LEFW_SPACING_END) {
    return LEFW_BAD_ORDER;
  }
  // can be right after a via or spacing defined in nondefaultrule
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", ruleName);
  } else {
    fprintf(lefwFile, "END %s\n\n", ruleName);
  }

  lefwLines++;
  lefwState = LEFW_NONDEFAULTRULE_END;
  lefwDidLayer = 0;
  lefwIsNonDefaultRule = 0;
  return LEFW_OK;
}

int lefwStartSpacing()
{
  lefwObsoleteNum = LEFW_SPACING;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_SPACING_START || lefwState == LEFW_SPACING) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END
      && (!lefwIsNonDefaultRule)) {  // spacing defined in nondefaultrule
    return LEFW_BAD_ORDER;           // not of the ENDs
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "SPACING\n");
  } else {
    fprintf(lefwFile, "SPACING\n");
  }

  lefwLines++;
  lefwState = LEFW_SPACING_START;
  return LEFW_OK;
}

int lefwSpacing(const char* layerName1,
                const char* layerName2,
                double minSpace,
                const char* stack)
{  // optioanl
  lefwObsoleteNum = LEFW_SPACING;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_SPACING_START && lefwState != LEFW_SPACING) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName1 || layerName1 == nullptr || *layerName1 == 0) {
    return LEFW_BAD_DATA;
  }
  if (!layerName2 || layerName2 == nullptr || *layerName2 == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   SAMENET %s %s %.11g ",
             layerName1,
             layerName2,
             minSpace);
    if (stack && strcmp(stack, "STACK") == 0) {
      encPrint(lefwFile, (char*) "STACK ");
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(
        lefwFile, "   SAMENET %s %s %.11g ", layerName1, layerName2, minSpace);
    if (stack && strcmp(stack, "STACK") == 0) {
      fprintf(lefwFile, "STACK ");
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_SPACING;
  return LEFW_OK;
}

int lefwEndSpacing()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_SPACING_START && lefwState != LEFW_SPACING) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END SPACING\n\n");
  } else {
    fprintf(lefwFile, "END SPACING\n\n");
  }

  lefwLines++;
  lefwState = LEFW_SPACING_END;
  return LEFW_OK;
}

int lefwUniversalNoiseMargin(double high, double low)
{
  lefwObsoleteNum = LEFW_NOISEMARGIN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_NOISEMARGIN]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "UNIVERSALNOISEMARGIN %.11g %.11g ;\n", high, low);
  } else {
    fprintf(lefwFile, "UNIVERSALNOISEMARGIN %.11g %.11g ;\n", high, low);
  }
  lefwSynArray[LEFW_NOISEMARGIN] = 1;
  return LEFW_OK;
}

int lefwEdgeRateThreshold1(double num)
{
  lefwObsoleteNum = LEFW_THRESHOLD1;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_THRESHOLD1]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "EDGERATETHRESHOLD1 %.11g ;\n", num);
  } else {
    fprintf(lefwFile, "EDGERATETHRESHOLD1 %.11g ;\n", num);
  }
  lefwSynArray[LEFW_THRESHOLD1] = 1;
  return LEFW_OK;
}

int lefwEdgeRateThreshold2(double num)
{
  lefwObsoleteNum = LEFW_THRESHOLD2;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_THRESHOLD2]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "EDGERATETHRESHOLD2 %.11g ;\n", num);
  } else {
    fprintf(lefwFile, "EDGERATETHRESHOLD2 %.11g ;\n", num);
  }
  lefwSynArray[LEFW_THRESHOLD2] = 1;
  return LEFW_OK;
}

int lefwEdgeRateScaleFactor(double num)
{
  lefwObsoleteNum = LEFW_SCALEFACTOR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_SCALEFACTOR]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "EDGERATESCALEFACTOR %.11g ;\n", num);
  } else {
    fprintf(lefwFile, "EDGERATESCALEFACTOR %.11g ;\n", num);
  }
  lefwSynArray[LEFW_SCALEFACTOR] = 1;
  return LEFW_OK;
}

int lefwStartNoiseTable(int num)
{
  lefwObsoleteNum = LEFW_NOISETABLE_START;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_NOISETABLE_START || lefwState == LEFW_NOISETABLE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_NOISETABLE_START]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "NOISETABLE %d ;\n", num);
  } else {
    fprintf(lefwFile, "NOISETABLE %d ;\n", num);
  }

  lefwLines++;
  lefwState = LEFW_NOISETABLE_START;
  lefwIsNoiseTable = 1;
  lefwIsEdgerate = 0;
  lefwSynArray[LEFW_NOISETABLE_START] = 1;
  return LEFW_OK;
}

// for both noisetable and correctiontable
// Obsolete in 5.4
int lefwEdgeRate(double num)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsNoiseTable && !lefwIsCorrectTable) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   EDGERATE %.11g ;\n", num);
  } else {
    fprintf(lefwFile, "   EDGERATE %.11g ;\n", num);
  }

  lefwLines++;
  if (lefwState == LEFW_NOISETABLE_START) {
    lefwState = LEFW_NOISETABLE;
  } else if (lefwState == LEFW_CORRECTTABLE_START) {
    lefwState = LEFW_CORRECTTABLE;
  }
  lefwIsEdgerate = 1;
  lefwIsOutResist = 0;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwOutputResistance(int numResists, double* resistance)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsEdgerate) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsOutResist) {
    return LEFW_BAD_ORDER;
  }

  if (numResists <= 0) {
    return LEFW_OK;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   OUTPUTRESISTANCE ");
    for (i = 0; i < numResists; i++) {
      encPrint(lefwFile, (char*) "%.11g ", *resistance++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   OUTPUTRESISTANCE ");
    for (i = 0; i < numResists; i++) {
      fprintf(lefwFile, "%.11g ", *resistance++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwIsOutResist = 1;
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwVictims(int length, int numNoises, double* noises)
{
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsOutResist) {
    return LEFW_BAD_ORDER;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      VICTIMLENGTH %d ;\n", length);
    if (numNoises <= 0) {
      return LEFW_BAD_DATA;  // noises are required
    }
    for (i = 0; i < numNoises; i++) {
      if (lefwIsNoiseTable) {
        encPrint(lefwFile, (char*) "      VICTIMNOISE ");
      } else {
        encPrint(lefwFile, (char*) "      CORRECTIONFACTOR ");
      }
      encPrint(lefwFile, (char*) "%.11g ", *noises++);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      VICTIMLENGTH %d ;\n", length);
    if (numNoises <= 0) {
      return LEFW_BAD_DATA;  // noises are required
    }
    for (i = 0; i < numNoises; i++) {
      if (lefwIsNoiseTable) {
        fprintf(lefwFile, "      VICTIMNOISE ");
      } else {
        fprintf(lefwFile, "      CORRECTIONFACTOR ");
      }
      fprintf(lefwFile, "%.11g ", *noises++);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwEndNoiseTable()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_NOISETABLE_START && lefwState != LEFW_NOISETABLE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END NOISETABLE\n\n");
  } else {
    fprintf(lefwFile, "END NOISETABLE\n\n");
  }
  lefwLines++;

  lefwState = LEFW_NOISETABLE_END;
  lefwIsNoiseTable = 0;
  lefwIsOutResist = 0;
  return LEFW_OK;
}

int lefwStartCorrectTable(int num)
{
  lefwObsoleteNum = LEFW_CORRECTTABLE_START;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_CORRECTTABLE_START || lefwState == LEFW_CORRECTTABLE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwSynArray[LEFW_CORRECTTABLE_START]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "CORRECTIONTABLE %d ;\n", num);
  } else {
    fprintf(lefwFile, "CORRECTIONTABLE %d ;\n", num);
  }

  lefwLines++;
  lefwState = LEFW_CORRECTTABLE_START;
  lefwIsCorrectTable = 1;
  lefwIsEdgerate = 0;
  lefwSynArray[LEFW_CORRECTTABLE_START] = 1;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwEndCorrectTable()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_CORRECTTABLE_START && lefwState != LEFW_CORRECTTABLE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END CORRECTIONTABLE\n\n");
  } else {
    fprintf(lefwFile, "END CORRECTIONTABLE\n\n");
  }
  lefwLines++;

  lefwState = LEFW_CORRECTTABLE_END;
  lefwIsNoiseTable = 0;
  return LEFW_OK;
}

int lefwMinFeature(double x, double y)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_MINFEATURE]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "MINFEATURE %.11g %.11g ;\n", x, y);
  } else {
    fprintf(lefwFile, "MINFEATURE %.11g %.11g ;\n", x, y);
  }
  lefwSynArray[LEFW_MINFEATURE] = 1;
  return LEFW_OK;
}

// *********************
//  int lefwDielectric (float dielectric) {
//    if (! lefwFile) return LEFW_UNINITIALIZED;
//    if (! lefwDidInit) return LEFW_BAD_ORDER;
//    if (lefwState != LEFW_INIT && lefwState < LEFW_END)
//       return LEFW_BAD_ORDER;
//    if (lefwSynArray[LEFW_DIELECTRIC]) return LEFW_ALREADY_DEFINED;
//    fprintf(lefwFile, "DIELECTRIC %.11g ;\n", dielectric);
//    lefwSynArray[LEFW_DIELECTRIC] = 1;
//    return LEFW_OK;
//  }
// ********************

int lefwStartIrdrop()
{
  lefwObsoleteNum = LEFW_IRDROP_START;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_IRDROP_START || lefwState == LEFW_IRDROP) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_IRDROP_START]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "IRDROP\n");
  } else {
    fprintf(lefwFile, "IRDROP\n");
  }

  lefwLines++;
  lefwState = LEFW_IRDROP_START;
  lefwSynArray[LEFW_IRDROP_START] = 1;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwIrdropTable(const char* tableName, const char* currentsNvolts)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_IRDROP_START && lefwState != LEFW_IRDROP) {
    return LEFW_BAD_ORDER;
  }
  if (!tableName || tableName == nullptr || *tableName == 0) {
    return LEFW_BAD_DATA;
  }
  if (!currentsNvolts || currentsNvolts == nullptr || *currentsNvolts == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   TABLE %s %s ;\n", tableName, currentsNvolts);
  } else {
    fprintf(lefwFile, "   TABLE %s %s ;\n", tableName, currentsNvolts);
  }
  lefwLines++;

  lefwState = LEFW_IRDROP;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwEndIrdrop()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_IRDROP_START && lefwState != LEFW_IRDROP) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END IRDROP\n\n");
  } else {
    fprintf(lefwFile, "END IRDROP\n\n");
  }
  lefwLines++;

  lefwState = LEFW_IRDROP_END;
  return LEFW_OK;
}

int lefwSite(const char* siteName,
             const char* classType,
             const char* symmetry,
             double width,
             double height)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_SITE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (!siteName || siteName == nullptr || *siteName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "SITE %s\n", siteName);
    if (classType && strcmp(classType, "PAD") && strcmp(classType, "CORE")) {
      return LEFW_BAD_DATA;
    }
    encPrint(lefwFile, (char*) "   CLASS %s ;\n", classType);
    if (symmetry) {
      encPrint(lefwFile, (char*) "   SYMMETRY %s ;\n", symmetry);
    }
    encPrint(lefwFile, (char*) "   SIZE %.11g BY %.11g ;\n", width, height);
    // encPrint(lefwFile, (char*)"END %s\n\n", siteName);
  } else {
    fprintf(lefwFile, "SITE %s\n", siteName);
    if (classType && strcmp(classType, "PAD") && strcmp(classType, "CORE")) {
      return LEFW_BAD_DATA;
    }
    fprintf(lefwFile, "   CLASS %s ;\n", classType);
    if (symmetry) {
      fprintf(lefwFile, "   SYMMETRY %s ;\n", symmetry);
    }
    fprintf(lefwFile, "   SIZE %.11g BY %.11g ;\n", width, height);
    // a separate function call, lefwEndSite
    // fprintf(lefwFile, "END %s\n\n", siteName);
  }

  lefwLines = lefwLines + 4;
  lefwSynArray[LEFW_SITE] = 1;
  lefwState = LEFW_SITE;
  return LEFW_OK;
}

int lefwSiteRowPattern(const char* siteName, int orient)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_SITE) {
    return LEFW_BAD_ORDER;
  }
  if (!siteName || siteName == nullptr || *siteName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   ROWPATTERN %s %s ;\n",
             siteName,
             lefwOrient(orient));
  } else {
    fprintf(lefwFile, "   ROWPATTERN %s %s ;\n", siteName, lefwOrient(orient));
  }
  lefwLines++;
  lefwState = LEFW_SITE;
  return LEFW_OK;
}

int lefwSiteRowPatternStr(const char* siteName, const char* orient)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_SITE) {
    return LEFW_BAD_ORDER;
  }
  if (!siteName || siteName == nullptr || *siteName == 0) {
    return LEFW_BAD_DATA;
  }
  if (!orient || orient == nullptr || *orient == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ROWPATTERN %s %s ;\n", siteName, orient);
  } else {
    fprintf(lefwFile, "   ROWPATTERN %s %s ;\n", siteName, orient);
  }
  lefwLines++;
  lefwState = LEFW_SITE;
  return LEFW_OK;
}

int lefwEndSite(const char* siteName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_SITE) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", siteName);
  } else {
    fprintf(lefwFile, "END %s\n\n", siteName);
  }

  lefwLines++;
  lefwState = LEFW_SITE_END;
  return LEFW_OK;
}

int lefwStartArray(const char* arrayName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_ARRAY_START || lefwState == LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (!arrayName || arrayName == nullptr || *arrayName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "ARRAY %s\n", arrayName);
  } else {
    fprintf(lefwFile, "ARRAY %s\n", arrayName);
  }

  lefwLines++;
  lefwState = LEFW_ARRAY_START;
  lefwSynArray[LEFW_ARRAY_START] = 1;
  lefwHasArrayReq = 0;
  lefwIsArrayFloorp = 0;
  return LEFW_OK;
}

int lefwArraySite(const char* name,
                  double origX,
                  double origY,
                  int orient,
                  double numX,
                  double numY,
                  double spaceX,
                  double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   SITE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, lefwOrient(orient), numX, numY, spaceX, spaceY);
  } else {
    fprintf(lefwFile,
            "   SITE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
            name,
            origX,
            origY,
            lefwOrient(orient),
            numX,
            numY,
            spaceX,
            spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArraySiteStr(const char* name,
                     double origX,
                     double origY,
                     const char* orient,
                     double numX,
                     double numY,
                     double spaceX,
                     double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   SITE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, orient, numX, numY, spaceX, spaceY);
  } else {
    fprintf(lefwFile,
            "   SITE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
            name,
            origX,
            origY,
            orient,
            numX,
            numY,
            spaceX,
            spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArrayCanplace(const char* name,
                      double origX,
                      double origY,
                      int orient,
                      double numX,
                      double numY,
                      double spaceX,
                      double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   CANPLACE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, lefwOrient(orient), numX, numY, spaceX, spaceY);
  } else {
    fprintf(
        lefwFile,
        "   CANPLACE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
        name,
        origX,
        origY,
        lefwOrient(orient),
        numX,
        numY,
        spaceX,
        spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArrayCanplaceStr(const char* name,
                         double origX,
                         double origY,
                         const char* orient,
                         double numX,
                         double numY,
                         double spaceX,
                         double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   CANPLACE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, orient, numX, numY, spaceX, spaceY);
  } else {
    fprintf(
        lefwFile,
        "   CANPLACE %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
        name,
        origX,
        origY,
        orient,
        numX,
        numY,
        spaceX,
        spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArrayCannotoccupy(const char* name,
                          double origX,
                          double origY,
                          int orient,
                          double numX,
                          double numY,
                          double spaceX,
                          double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   CANNOTOCCUPY %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, lefwOrient(orient), numX, numY, spaceX, spaceY);
  } else {
    fprintf(lefwFile,
            "   CANNOTOCCUPY %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g "
            "%.11g ;\n",
            name,
            origX,
            origY,
            lefwOrient(orient),
            numX,
            numY,
            spaceX,
            spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArrayCannotoccupyStr(const char* name,
                             double origX,
                             double origY,
                             const char* orient,
                             double numX,
                             double numY,
                             double spaceX,
                             double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*)
                 "   CANNOTOCCUPY %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g %.11g ;\n",
                 name, origX, origY, orient, numX, numY, spaceX, spaceY);
  } else {
    fprintf(lefwFile,
            "   CANNOTOCCUPY %s %.11g %.11g %s DO %.11g BY %.11g STEP %.11g "
            "%.11g ;\n",
            name,
            origX,
            origY,
            orient,
            numX,
            numY,
            spaceX,
            spaceY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwArrayTracks(const char* xy,
                    double start,
                    int numTracks,
                    double space,
                    const char* layers)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!xy || xy == nullptr || *xy == 0) {
    return LEFW_BAD_DATA;
  }
  if (strcmp(xy, "X") && strcmp(xy, "Y")) {
    return LEFW_BAD_DATA;
  }
  if (!layers || layers == nullptr || *layers == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   TRACKS %s %.11g DO %d STEP %.11g LAYER %s ;\n",
             xy,
             start,
             numTracks,
             space,
             layers);
  } else {
    fprintf(lefwFile,
            "   TRACKS %s %.11g DO %d STEP %.11g LAYER %s ;\n",
            xy,
            start,
            numTracks,
            space,
            layers);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwStartArrayFloorplan(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsArrayFloorp) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FLOORPLAN %s\n", name);
  } else {
    fprintf(lefwFile, "   FLOORPLAN %s\n", name);
  }

  lefwLines++;
  lefwHasArrayReq = 1;
  lefwIsArrayFloorp = 1;
  return LEFW_OK;
}

int lefwArrayFloorplan(const char* site,
                       const char* name,
                       double origX,
                       double origY,
                       int orient,
                       int numX,
                       int numY,
                       double spaceX,
                       double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsArrayFloorp) {
    return LEFW_BAD_ORDER;
  }
  if (site && strcmp(site, "CANPLACE") && strcmp(site, "CANNOTOCCUPY")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile,
        (char*) "      %s %s %.11g %.11g %s DO %d BY %d STEP %.11g %.11g ;\n",
        site,
        name,
        origX,
        origY,
        lefwOrient(orient),
        numX,
        numY,
        spaceX,
        spaceY);
  } else {
    fprintf(lefwFile,
            "      %s %s %.11g %.11g %s DO %d BY %d STEP %.11g %.11g ;\n",
            site,
            name,
            origX,
            origY,
            lefwOrient(orient),
            numX,
            numY,
            spaceX,
            spaceY);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwArrayFloorplanStr(const char* site,
                          const char* name,
                          double origX,
                          double origY,
                          const char* orient,
                          int numX,
                          int numY,
                          double spaceX,
                          double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsArrayFloorp) {
    return LEFW_BAD_ORDER;
  }
  if (site && strcmp(site, "CANPLACE") && strcmp(site, "CANNOTOCCUPY")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile,
        (char*) "      %s %s %.11g %.11g %s DO %d BY %d STEP %.11g %.11g ;\n",
        site,
        name,
        origX,
        origY,
        orient,
        numX,
        numY,
        spaceX,
        spaceY);
  } else {
    fprintf(lefwFile,
            "      %s %s %.11g %.11g %s DO %d BY %d STEP %.11g %.11g ;\n",
            site,
            name,
            origX,
            origY,
            orient,
            numX,
            numY,
            spaceX,
            spaceY);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwEndArrayFloorplan(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsArrayFloorp) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END %s\n\n", name);
  } else {
    fprintf(lefwFile, "   END %s\n\n", name);
  }

  lefwLines++;
  lefwIsArrayFloorp = 0;
  return LEFW_OK;
}

int lefwArrayGcellgrid(const char* xy,
                       double startXY,
                       int colRows,
                       double spaceXY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!xy || xy == nullptr || *xy == 0) {
    return LEFW_BAD_DATA;
  }
  if (strcmp(xy, "X") && strcmp(xy, "Y")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "   GCELLGRID %s %.11g DO %d STEP %.11g ;\n",
             xy,
             startXY,
             colRows,
             spaceXY);
  } else {
    fprintf(lefwFile,
            "   GCELLGRID %s %.11g DO %d STEP %.11g ;\n",
            xy,
            startXY,
            colRows,
            spaceXY);
  }

  lefwLines++;
  lefwHasArrayReq = 1;

  lefwState = LEFW_ARRAY;
  return LEFW_OK;
}

int lefwStartArrayDefaultCap(int size)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsArrayDef) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DEFAULTCAP %d\n", size);
  } else {
    fprintf(lefwFile, "   DEFAULTCAP %d\n", size);
  }

  lefwLines++;
  lefwIsArrayDef = 1;
  return LEFW_OK;
}

int lefwArrayDefaultCap(double numPins, double cap)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsArrayDef) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "      MINPINS %.11g WIRECAP %.11g ;\n",
             numPins,
             cap);
  } else {
    fprintf(lefwFile, "      MINPINS %.11g WIRECAP %.11g ;\n", numPins, cap);
  }
  lefwLines++;
  return LEFW_OK;
}

int lefwEndArrayDefaultCap()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwIsArrayDef) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END DEFAULTCAP\n\n");
  } else {
    fprintf(lefwFile, "   END DEFAULTCAP\n\n");
  }

  lefwLines++;
  lefwIsArrayDef = 0;
  return LEFW_OK;
}

int lefwEndArray(const char* arrayName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_ARRAY_START && lefwState != LEFW_ARRAY) {
    return LEFW_BAD_ORDER;
  }
  if (!arrayName || arrayName == nullptr || *arrayName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwIsFloorp || lefwIsArrayDef) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", arrayName);
  } else {
    fprintf(lefwFile, "END %s\n\n", arrayName);
  }

  lefwLines++;
  lefwState = LEFW_ARRAY_END;
  return LEFW_OK;
}

int lefwStartMacro(const char* macroName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState == LEFW_MACRO_START || lefwState == LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!macroName || macroName == nullptr || *macroName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "MACRO %s\n", macroName);
  } else {
    fprintf(lefwFile, "MACRO %s\n", macroName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO_START;
  lefwIsMacroDensity = 0;
  lefwIsMacroPin = 0;
  lefwIsMacroObs = 0;
  lefwIsMacroTiming = 0;
  return LEFW_OK;
}

int lefwMacroClass(const char* value1, const char* value2)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!value1 || value1 == nullptr || *value1 == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    if (strcmp(value1, "RING") == 0) {
      encPrint(lefwFile, (char*) "   CLASS %s ;\n", value1);
    } else if (strcmp(value1, "BLOCK") == 0) {
      if (value2) {
        if (strcmp(value2, "BLACKBOX") && strcmp(value2, "SOFT")) {
          return LEFW_BAD_DATA;
        }
        encPrint(lefwFile, (char*) "   CLASS %s %s ;\n", value1, value2);
      } else {
        encPrint(lefwFile, (char*) "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "COVER") == 0) {
      if (value2) {
        if (strcmp(value2, "BUMP")) {
          return LEFW_BAD_DATA;
        }
        encPrint(lefwFile, (char*) "   CLASS %s %s ;\n", value1, value2);
      } else {
        encPrint(lefwFile, (char*) "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "PAD") == 0) {
      if (value2) {
        if (strcmp(value2, "INPUT") && strcmp(value2, "OUTPUT")
            && strcmp(value2, "INOUT") && strcmp(value2, "POWER")
            && strcmp(value2, "SPACER") && strcmp(value2, "AREAIO")) {
          return LEFW_BAD_DATA;
        }
        encPrint(lefwFile, (char*) "   CLASS %s %s ;\n", value1, value2);
      } else {
        encPrint(lefwFile, (char*) "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "CORE") == 0) {
      if (value2) {
        if (strcmp(value2, "FEEDTHRU") && strcmp(value2, "TIEHIGH")
            && strcmp(value2, "TIELOW") && strcmp(value2, "SPACER")
            && strcmp(value2, "ANTENNACELL") && strcmp(value2, "WELLTAP")) {
          return LEFW_BAD_DATA;
        }
        encPrint(lefwFile, (char*) "   CLASS %s %s ;\n", value1, value2);
      } else {
        encPrint(lefwFile, (char*) "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "ENDCAP") == 0) {
      if (value2) {
        if (strcmp(value2, "PRE") && strcmp(value2, "POST")
            && strcmp(value2, "TOPLEFT") && strcmp(value2, "TOPRIGHT")
            && strcmp(value2, "BOTTOMLEFT") && strcmp(value2, "BOTTOMRIGHT")) {
          return LEFW_BAD_DATA;
        }
        encPrint(lefwFile, (char*) "   CLASS %s %s ;\n", value1, value2);
      } else {
        return LEFW_BAD_DATA;  // require 2nd value
      }
    } else {
      return LEFW_BAD_DATA;
    }
  } else {
    if (strcmp(value1, "RING") == 0) {
      fprintf(lefwFile, "   CLASS %s ;\n", value1);
    } else if (strcmp(value1, "BLOCK") == 0) {
      if (value2) {
        if (strcmp(value2, "BLACKBOX") && strcmp(value2, "SOFT")) {
          return LEFW_BAD_DATA;
        }
        fprintf(lefwFile, "   CLASS %s %s ;\n", value1, value2);
      } else {
        fprintf(lefwFile, "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "COVER") == 0) {
      if (value2) {
        if (strcmp(value2, "BUMP")) {
          return LEFW_BAD_DATA;
        }
        fprintf(lefwFile, "   CLASS %s %s ;\n", value1, value2);
      } else {
        fprintf(lefwFile, "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "PAD") == 0) {
      if (value2) {
        if (strcmp(value2, "INPUT") && strcmp(value2, "OUTPUT")
            && strcmp(value2, "INOUT") && strcmp(value2, "POWER")
            && strcmp(value2, "SPACER") && strcmp(value2, "AREAIO")) {
          return LEFW_BAD_DATA;
        }
        fprintf(lefwFile, "   CLASS %s %s ;\n", value1, value2);
      } else {
        fprintf(lefwFile, "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "CORE") == 0) {
      if (value2) {
        if (strcmp(value2, "FEEDTHRU") && strcmp(value2, "TIEHIGH")
            && strcmp(value2, "TIELOW") && strcmp(value2, "SPACER")
            && strcmp(value2, "ANTENNACELL") && strcmp(value2, "WELLTAP")) {
          return LEFW_BAD_DATA;
        }
        fprintf(lefwFile, "   CLASS %s %s ;\n", value1, value2);
      } else {
        fprintf(lefwFile, "   CLASS %s ;\n", value1);
      }
    } else if (strcmp(value1, "ENDCAP") == 0) {
      if (value2) {
        if (strcmp(value2, "PRE") && strcmp(value2, "POST")
            && strcmp(value2, "TOPLEFT") && strcmp(value2, "TOPRIGHT")
            && strcmp(value2, "BOTTOMLEFT") && strcmp(value2, "BOTTOMRIGHT")) {
          return LEFW_BAD_DATA;
        }
        fprintf(lefwFile, "   CLASS %s %s ;\n", value1, value2);
      } else {
        return LEFW_BAD_DATA;  // require 2nd value
      }
    } else {
      return LEFW_BAD_DATA;
    }
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroFixedMask()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }

  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }

  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }

  if (versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FIXEDMASK ;\n");
  } else {
    fprintf(lefwFile, "   FIXEDMASK ;\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSource(const char* value1)
{
  lefwObsoleteNum = LEFW_MACRO_SOURCE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (!value1 || value1 == nullptr || *value1 == 0) {
    return LEFW_BAD_DATA;
  }
  if (strcmp(value1, "USER") == 0 || strcmp(value1, "GENERATE") == 0
      || strcmp(value1, "BLOCK") == 0) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "   SOURCE %s ;\n", value1);
    } else {
      fprintf(lefwFile, "   SOURCE %s ;\n", value1);
    }
  } else {
    return LEFW_BAD_DATA;
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroForeign(const char* name, double xl, double yl, int orient)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FOREIGN %s ", name);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0, 0 pt
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   FOREIGN %s ", name);
    if (xl || yl) {
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        fprintf(lefwFile, "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0, 0 pt
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", lefwOrient(orient));
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroForeignStr(const char* name,
                        double xl,
                        double yl,
                        const char* orient)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   FOREIGN %s ", name);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        encPrint(lefwFile, (char*) "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0, 0 pt
      encPrint(lefwFile, (char*) "%.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", orient);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   FOREIGN %s ", name);
    if (xl || yl) {
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        fprintf(lefwFile, "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0, 0 pt
      fprintf(lefwFile, "%.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", orient);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroOrigin(double xl, double yl)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ORIGIN %.11g %.11g ;\n", xl, yl);
  } else {
    fprintf(lefwFile, "   ORIGIN %.11g %.11g ;\n", xl, yl);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroEEQ(const char* macroName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!macroName || macroName == nullptr || *macroName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   EEQ %s ;\n", macroName);
  } else {
    fprintf(lefwFile, "   EEQ %s ;\n", macroName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroLEQ(const char* macroName)
{
  lefwObsoleteNum = LEFW_MACRO_LEQ;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (!macroName || macroName == nullptr || *macroName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   LEQ %s ;\n", macroName);
  } else {
    fprintf(lefwFile, "   LEQ %s ;\n", macroName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSize(double width, double height)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SIZE %.11g BY %.11g ;\n", width, height);
  } else {
    fprintf(lefwFile, "   SIZE %.11g BY %.11g ;\n", width, height);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSymmetry(const char* symmetry)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!symmetry || symmetry == nullptr || *symmetry == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SYMMETRY %s ;\n", symmetry);
  } else {
    fprintf(lefwFile, "   SYMMETRY %s ;\n", symmetry);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSite(const char* siteName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!siteName || siteName == nullptr || *siteName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SITE %s ;\n", siteName);
  } else {
    fprintf(lefwFile, "   SITE %s ;\n", siteName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSitePattern(const char* name,
                         double origX,
                         double origY,
                         int orient,
                         int numX,
                         int numY,
                         double spaceX,
                         double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SITE %s ", name);
    if (origX || origY || (orient != 1)) {
      encPrint(lefwFile,
               (char*) "%.11g %.11g %s ",
               origX,
               origY,
               lefwOrient(orient));
      if (numX || numY || spaceX || spaceY) {
        encPrint(lefwFile,
                 (char*) "DO %d BY %d STEP %.11g %.11g ",
                 numX,
                 numY,
                 spaceX,
                 spaceY);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   SITE %s ", name);
    if (origX || origY || (orient != 1)) {
      fprintf(lefwFile, "%.11g %.11g %s ", origX, origY, lefwOrient(orient));
      if (numX || numY || spaceX || spaceY) {
        fprintf(lefwFile,
                "DO %d BY %d STEP %.11g %.11g ",
                numX,
                numY,
                spaceX,
                spaceY);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroSitePatternStr(const char* name,
                            double origX,
                            double origY,
                            const char* orient,
                            int numX,
                            int numY,
                            double spaceX,
                            double spaceY)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   SITE %s ", name);
    if (origX || origY || orient) {
      encPrint(lefwFile, (char*) "%.11g %.11g %s ", origX, origY, orient);
      if (numX || numY || spaceX || spaceY) {
        encPrint(lefwFile,
                 (char*) "DO %d BY %d STEP %.11g %.11g ",
                 numX,
                 numY,
                 spaceX,
                 spaceY);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "   SITE %s ", name);
    if (origX || origY || orient) {
      fprintf(lefwFile, "%.11g %.11g %s ", origX, origY, orient);
      if (numX || numY || spaceX || spaceY) {
        fprintf(lefwFile,
                "DO %d BY %d STEP %.11g %.11g ",
                numX,
                numY,
                spaceX,
                spaceY);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPower(double power)
{
  lefwObsoleteNum = LEFW_MACRO_POWER;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   POWER %.11g ;\n", power);
  } else {
    fprintf(lefwFile, "   POWER %.11g ;\n", power);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwEndMacro(const char* macroName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (!macroName || macroName == nullptr || *macroName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "END %s\n\n", macroName);
  } else {
    fprintf(lefwFile, "END %s\n\n", macroName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO_END;
  return LEFW_OK;
}

int lefwStartMacroDensity(const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsMacroDensity) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   DENSITY %s\n", layerName);
  } else {
    fprintf(lefwFile, "   DENSITY %s\n", layerName);
  }

  lefwState = LEFW_MACRO;
  lefwIsMacroDensity = 1;
  lefwLines++;
  return LEFW_OK;
}

int lefwMacroDensityLayerRect(double x1,
                              double y1,
                              double x2,
                              double y2,
                              double densityValue)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroDensity) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "      RECT %.11g %.11g %.11g %.11g %.11g ;\n",
             x1,
             y1,
             x2,
             y2,
             densityValue);
  } else {
    fprintf(lefwFile,
            "      RECT %.11g %.11g %.11g %.11g %.11g ;\n",
            x1,
            y1,
            x2,
            y2,
            densityValue);
  }
  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwEndMacroDensity()
{
  if (!lefwIsMacroDensity) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END\n\n");
  } else {
    fprintf(lefwFile, "   END\n\n");
  }

  lefwLines++;
  lefwIsMacroDensity = 0;
  return LEFW_OK;
}

int lefwStartMacroPin(const char* pinName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!pinName || pinName == nullptr || *pinName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   PIN %s\n", pinName);
  } else {
    fprintf(lefwFile, "   PIN %s\n", pinName);
  }

  lefwIsMacroPin = 1;
  lefwIsMacroPinPort = 0;  // port within macropin
  lefwLines++;
  lefwAMaxAreaCar = 0;      // reset
  lefwAMaxSideAreaCar = 0;  // reset
  lefwAMaxCutCar = 0;       // reset
  return LEFW_OK;
}

int lefwMacroPinTaperRule(const char* ruleName)
{  // opitonal
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!ruleName || ruleName == nullptr || *ruleName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      TAPERRULE %s ;\n", ruleName);
  } else {
    fprintf(lefwFile, "      TAPERRULE %s ;\n", ruleName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinForeign(const char* name, double xl, double yl, int orient)
{  // optional
  lefwObsoleteNum = LEFW_MACRO_PINFOREIGN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FOREIGN %s ", name);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "STRUCTURE %.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0 0 for pt
      encPrint(lefwFile, (char*) "STRUCTURE %.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", lefwOrient(orient));
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      FOREIGN %s ", name);
    if (xl || yl) {
      fprintf(lefwFile, "STRUCTURE %.11g %.11g ", xl, yl);
      if (orient >= 0 && orient <= 7) {
        fprintf(lefwFile, "%s ", lefwOrient(orient));
      }
    } else if (orient > 0 && orient <= 7) {  // assume user has 0 0 for pt
      fprintf(lefwFile, "STRUCTURE %.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", lefwOrient(orient));
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinForeignStr(const char* name,
                           double xl,
                           double yl,  // optional
                           const char* orient)
{  // optional
  lefwObsoleteNum = LEFW_MACRO_PINFOREIGN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FOREIGN %s ", name);
    if (xl || yl) {
      encPrint(lefwFile, (char*) "STRUCTURE %.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        encPrint(lefwFile, (char*) "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0 0 for pt
      encPrint(lefwFile, (char*) "STRUCTURE %.11g %.11g ", xl, yl);
      encPrint(lefwFile, (char*) "%s ", orient);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      FOREIGN %s ", name);
    if (xl || yl) {
      fprintf(lefwFile, "STRUCTURE %.11g %.11g ", xl, yl);
      if (orient && *orient != '\0') {
        fprintf(lefwFile, "%s ", orient);
      }
    } else if (orient && *orient != '\0') {  // assume user has 0 0 for pt
      fprintf(lefwFile, "STRUCTURE %.11g %.11g ", xl, yl);
      fprintf(lefwFile, "%s ", orient);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinLEQ(const char* pinName)
{
  lefwObsoleteNum = LEFW_MACRO_PINLEQ;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.6) {
    return LEFW_OBSOLETE;
  }
  if (!pinName || pinName == nullptr || *pinName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      LEQ %s ;\n", pinName);
  } else {
    fprintf(lefwFile, "      LEQ %s ;\n", pinName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinDirection(const char* direction)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!direction || direction == nullptr || *direction == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      DIRECTION %s ;\n", direction);
  } else {
    fprintf(lefwFile, "      DIRECTION %s ;\n", direction);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinUse(const char* use)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!use || use == nullptr || *use == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      USE %s ;\n", use);
  } else {
    fprintf(lefwFile, "      USE %s ;\n", use);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinShape(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    if (!name || name == nullptr || *name == 0) {
      encPrint(lefwFile, (char*) "      SHAPE ;\n");
    } else {
      encPrint(lefwFile, (char*) "      SHAPE %s ;\n", name);
    }
  } else {
    if (!name || name == nullptr || *name == 0) {
      fprintf(lefwFile, "      SHAPE ;\n");
    } else {
      fprintf(lefwFile, "      SHAPE %s ;\n", name);
    }
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinMustjoin(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      MUSTJOIN %s ;\n", name);
  } else {
    fprintf(lefwFile, "      MUSTJOIN %s ;\n", name);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinNetExpr(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      NETEXPR \"%s\" ;\n", name);
  } else {
    fprintf(lefwFile, "      NETEXPR \"%s\" ;\n", name);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinSupplySensitivity(const char* pinName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!pinName || pinName == nullptr || *pinName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      SUPPLYSENSITIVITY %s ;\n", pinName);
  } else {
    fprintf(lefwFile, "      SUPPLYSENSITIVITY %s ;\n", pinName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinGroundSensitivity(const char* pinName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!pinName || pinName == nullptr || *pinName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      GROUNDSENSITIVITY %s ;\n", pinName);
  } else {
    fprintf(lefwFile, "      GROUNDSENSITIVITY %s ;\n", pinName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinOutputnoisemargin(int high, int low)
{
  lefwObsoleteNum = LEFW_MACRO_OUTPUTNOISEMARGIN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      OUTPUTNOISEMARGIN %d %d ;\n", high, low);
  } else {
    fprintf(lefwFile, "      OUTPUTNOISEMARGIN %d %d ;\n", high, low);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinOutputresistance(int high, int low)
{
  lefwObsoleteNum = LEFW_MACRO_OUTPUTRESISTANCE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      OUTPUTRESISTANCE %d %d ;\n", high, low);
  } else {
    fprintf(lefwFile, "      OUTPUTRESISTANCE %d %d ;\n", high, low);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinInputnoisemargin(int high, int low)
{
  lefwObsoleteNum = LEFW_MACRO_INPUTNOISEMARGIN;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      INPUTNOISEMARGIN %d %d ;\n", high, low);
  } else {
    fprintf(lefwFile, "      INPUTNOISEMARGIN %d %d ;\n", high, low);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinPower(double power)
{
  lefwObsoleteNum = LEFW_MACRO_POWER;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      POWER %.11g ;\n", power);
  } else {
    fprintf(lefwFile, "      POWER %.11g ;\n", power);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinLeakage(double leakage)
{
  lefwObsoleteNum = LEFW_MACRO_LEAKAGE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      LEAKAGE %.11g ;\n", leakage);
  } else {
    fprintf(lefwFile, "      LEAKAGE %.11g ;\n", leakage);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinCapacitance(double capacitance)
{
  lefwObsoleteNum = LEFW_MACRO_CAPACITANCE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      CAPACITANCE %.11g ;\n", capacitance);
  } else {
    fprintf(lefwFile, "      CAPACITANCE %.11g ;\n", capacitance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinResistance(double resistance)
{
  lefwObsoleteNum = LEFW_MACRO_RESISTANCE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RESISTANCE %.11g ;\n", resistance);
  } else {
    fprintf(lefwFile, "      RESISTANCE %.11g ;\n", resistance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinPulldownres(double resistance)
{
  lefwObsoleteNum = LEFW_MACRO_PULLDOWNRES;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      PULLDOWNRES %.11g ;\n", resistance);
  } else {
    fprintf(lefwFile, "      PULLDOWNRES %.11g ;\n", resistance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinTieoffr(double resistance)
{
  lefwObsoleteNum = LEFW_MACRO_TIEOFFR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      TIEOFFR %.11g ;\n", resistance);
  } else {
    fprintf(lefwFile, "      TIEOFFR %.11g ;\n", resistance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinVHI(double voltage)
{
  lefwObsoleteNum = LEFW_MACRO_VHI;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      VHI %.11g ;\n", voltage);
  } else {
    fprintf(lefwFile, "      VHI %.11g ;\n", voltage);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinVLO(double voltage)
{
  lefwObsoleteNum = LEFW_MACRO_VLO;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      VLO %.11g ;\n", voltage);
  } else {
    fprintf(lefwFile, "      VLO %.11g ;\n", voltage);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinRisevoltagethreshold(double voltage)
{
  lefwObsoleteNum = LEFW_MACRO_RISEVOLTAGETHRESHOLD;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISEVOLTAGETHRESHOLD %.11g ;\n", voltage);
  } else {
    fprintf(lefwFile, "      RISEVOLTAGETHRESHOLD %.11g ;\n", voltage);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinFallvoltagethreshold(double voltage)
{
  lefwObsoleteNum = LEFW_MACRO_FALLVOLTAGETHRESHOLD;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLVOLTAGETHRESHOLD %.11g ;\n", voltage);
  } else {
    fprintf(lefwFile, "      FALLVOLTAGETHRESHOLD %.11g ;\n", voltage);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinRisethresh(double capacitance)
{
  lefwObsoleteNum = LEFW_MACRO_RISETHRESH;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISETHRESH %.11g ;\n", capacitance);
  } else {
    fprintf(lefwFile, "      RISETHRESH %.11g ;\n", capacitance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinFallthresh(double capacitance)
{
  lefwObsoleteNum = LEFW_MACRO_FALLTHRESH;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLTHRESH %.11g ;\n", capacitance);
  } else {
    fprintf(lefwFile, "      FALLTHRESH %.11g ;\n", capacitance);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinRisesatcur(double current)
{
  lefwObsoleteNum = LEFW_MACRO_RISESATCUR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISESATCUR %.11g ;\n", current);
  } else {
    fprintf(lefwFile, "      RISESATCUR %.11g ;\n", current);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinFallsatcur(double current)
{
  lefwObsoleteNum = LEFW_MACRO_FALLSATCUR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLSATCUR %.11g ;\n", current);
  } else {
    fprintf(lefwFile, "      FALLSATCUR %.11g ;\n", current);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinCurrentsource(const char* name)
{
  lefwObsoleteNum = LEFW_MACRO_FALLCURRENTSOURCE;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (strcmp(name, "ACTIVE") && strcmp(name, "RESISTIVE")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      CURRENTSOURCE %s ;\n", name);
  } else {
    fprintf(lefwFile, "      CURRENTSOURCE %s ;\n", name);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinIV_Tables(const char* lowName, const char* highName)
{
  lefwObsoleteNum = LEFW_MACRO_IV_TABLES;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (!lowName || lowName == nullptr || *lowName == 0) {
    return LEFW_BAD_DATA;
  }
  if (!highName || highName == nullptr || *highName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      IV_TABLES %s %s ;\n", lowName, highName);
  } else {
    fprintf(lefwFile, "      IV_TABLES %s %s ;\n", lowName, highName);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinAntennasize(double value, const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwAntenna54) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNASIZE %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNASIZE %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna53 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaMetalArea(double value, const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMETALAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAMETALAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  return LEFW_OK;
}

int lefwMacroPinAntennaMetalLength(double value, const char* layerName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwAntenna54) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMETALLENGTH %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAMETALLENGTH %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna53 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaPartialMetalArea(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAPARTIALMETALAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAPARTIALMETALAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAPARTIALMETALAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaPartialMetalSideArea(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAPARTIALMETALSIDEAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "      ANTENNAPARTIALMETALSIDEAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAPARTIALMETALSIDEAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaPartialCutArea(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAPARTIALCUTAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAPARTIALCUTAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAPARTIALCUTAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaDiffArea(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNADIFFAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNADIFFAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNADIFFAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaModel(const char* oxide)
{
  lefw54Num = LEFW_ANTENNAGATEAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMODEL %s ;\n", oxide);
  } else {
    fprintf(lefwFile, "      ANTENNAMODEL %s ;\n", oxide);
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaGateArea(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAGATEAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAGATEAREA %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAGATEAREA %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaMaxAreaCar(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAMAXAREACAR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwAMaxAreaCar) {
    return LEFW_BAD_DATA;  // ANTENNAMAXAREACAR has defined
  }
  // more than once
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMAXAREACAR %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAMAXAREACAR %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaMaxSideAreaCar(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAMAXSIDEAREACAR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwAMaxSideAreaCar) {
    return LEFW_BAD_DATA;  // ANTENNAMAXSIDEAREACAR has
  }
  // defined more than once
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMAXSIDEAREACAR %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAMAXSIDEAREACAR %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwMacroPinAntennaMaxCutCar(double value, const char* layerName)
{
  lefw54Num = LEFW_ANTENNAMAXCUTCAR;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwAMaxCutCar) {
    return LEFW_BAD_DATA;  // ANTENNAMAXCUTCAR has
  }
  // defined more than once
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwAntenna53) {
    return LEFW_MIX_VERSION_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      ANTENNAMAXCUTCAR %.11g ", value);
    if (layerName) {
      encPrint(lefwFile, (char*) "LAYER %s ", layerName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      ANTENNAMAXCUTCAR %.11g ", value);
    if (layerName) {
      fprintf(lefwFile, "LAYER %s ", layerName);
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwState = LEFW_MACRO;
  lefwAntenna54 = 1;
  return LEFW_OK;
}

int lefwEndMacroPin(const char* pinName)
{
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (!pinName || pinName == nullptr || *pinName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END %s\n\n", pinName);
  } else {
    fprintf(lefwFile, "   END %s\n\n", pinName);
  }

  lefwLines++;
  lefwIsMacroPin = 0;
  return LEFW_OK;
}

int lefwStartMacroPinPort(const char* classType)
{  // optional

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPin) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    if (classType) {
      if (strcmp(classType, "NONE") && strcmp(classType, "CORE")) {
        return LEFW_BAD_DATA;
      }
      encPrint(lefwFile, (char*) "      PORT CLASS %s ;\n", classType);
    } else {
      encPrint(lefwFile, (char*) "      PORT \n");
    }
  } else {
    if (classType) {
      if (strcmp(classType, "NONE") && strcmp(classType, "CORE")
          && strcmp(classType, "BUMP")) {
        return LEFW_BAD_DATA;
      }
      fprintf(lefwFile, "      PORT CLASS %s ;\n", classType);
    } else {
      fprintf(lefwFile, "      PORT \n");
    }
  }

  lefwLines++;
  lefwIsMacroPinPort = 1;
  lefwIsMacroPinPortLayer = 0;
  lefwSpacingVal = 0;
  lefwWidthVal = 0;
  return LEFW_OK;
}

int lefwMacroPinPortLayer(const char* layerName, double spacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPort) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWidthVal) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "         LAYER %s ", layerName);
    if (spacing) {
      encPrint(lefwFile, (char*) "SPACING %.11g ", spacing);
    }
    encPrint(lefwFile, (char*) ";\n ");
  } else {
    fprintf(lefwFile, "         LAYER %s ", layerName);
    if (spacing) {
      fprintf(lefwFile, "SPACING %.11g ", spacing);
    }
    fprintf(lefwFile, ";\n ");
  }
  lefwLines++;
  lefwIsMacroPinPortLayer = 1;
  lefwSpacingVal = 1;
  return LEFW_OK;
}

int lefwMacroPinPortDesignRuleWidth(const char* layerName, double width)
{
  lefw54Num = LEFW_DESIGNRULEWIDTH;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPort) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwSpacingVal) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "         LAYER %s ", layerName);
    if (width) {
      encPrint(lefwFile, (char*) "DESIGNRULEWIDTH %.11g ", width);
    }
    encPrint(lefwFile, (char*) ";\n ");
  } else {
    fprintf(lefwFile, "         LAYER %s ", layerName);
    if (width) {
      fprintf(lefwFile, "DESIGNRULEWIDTH %.11g ", width);
    }
    fprintf(lefwFile, ";\n ");
  }
  lefwLines++;
  lefwIsMacroPinPortLayer = 1;
  lefwWidthVal = 1;
  return LEFW_OK;
}

int lefwMacroPinPortLayerWidth(double width)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPortLayer) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "         WIDTH %.11g ;\n", width);
  } else {
    fprintf(lefwFile, "         WIDTH %.11g ;\n", width);
  }
  lefwLines++;
  lefwIsMacroPinPortLayer = 1;
  return LEFW_OK;
}

int lefwMacroPinPortLayerPath(int num_paths,
                              double* xl,
                              double* yl,
                              int numX,
                              int numY,  // optional
                              double spaceX,
                              double spaceY,  // optional
                              int mask)
{  // optional
  int i, numItem;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPortLayer) {
    return LEFW_BAD_ORDER;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(lefwFile, (char*) "         PATH MASK %d ITERATE ", mask);
      } else {
        encPrint(lefwFile, (char*) "         PATH ITERATE ");
      }
      for (i = 0; i < num_paths; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g\n", xl[i], yl[i]);
        } else {
          encPrint(lefwFile, (char*) "           %.11g %.11g\n", xl[i], yl[i]);
        }
        lefwLines++;
      }
      encPrint(lefwFile,
               (char*) "           DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile, (char*) "         PATH MASK %d ", mask);
      } else {
        encPrint(lefwFile, (char*) "         PATH ");
      }
      numItem = 0;
      for (i = 0; i < num_paths; i++) {
        if (numItem > 5) {
          encPrint(lefwFile, (char*) "\n");
          encPrint(lefwFile, (char*) "           %.11g %.11g ", xl[i], yl[i]);
          numItem = 0;
          lefwLines++;
        } else {
          encPrint(lefwFile, (char*) "%.11g %.11g ", xl[i], yl[i]);
        }
        numItem++;
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile, "         PATH MASK %d ITERATE ", mask);
      } else {
        fprintf(lefwFile, "         PATH ITERATE ");
      }
      for (i = 0; i < num_paths; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g\n", xl[i], yl[i]);
        } else {
          fprintf(lefwFile, "           %.11g %.11g\n", xl[i], yl[i]);
        }
        lefwLines++;
      }
      fprintf(lefwFile,
              "           DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile, "         PATH MASK %d ", mask);
      } else {
        fprintf(lefwFile, "         PATH ");
      }
      numItem = 0;
      for (i = 0; i < num_paths; i++) {
        if (numItem > 5) {
          fprintf(lefwFile, "\n");
          fprintf(lefwFile, "           %.11g %.11g ", xl[i], yl[i]);
          numItem = 0;
          lefwLines++;
        } else {
          fprintf(lefwFile, "%.11g %.11g ", xl[i], yl[i]);
        }
        numItem++;
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroPinPortLayerRect(double xl1,
                              double yl1,
                              double xl2,
                              double yl2,
                              int numX,
                              int numY,  // optional
                              double spaceX,
                              double spaceY,  // optional
                              int mask)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPortLayer) {
    return LEFW_BAD_ORDER;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(
            lefwFile,
            (char*) "            RECT MASK %d ITERATE %.11g %.11g %.11g %.11g ",
            mask,
            xl1,
            yl1,
            xl2,
            yl2);
      } else {
        encPrint(lefwFile,
                 (char*) "            RECT ITERATE %.11g %.11g %.11g %.11g ",
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      }
      encPrint(lefwFile,
               (char*) "DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile,
                 (char*) "            RECT MASK %d %.11g %.11g %.11g %.11g ",
                 mask,
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      } else {
        encPrint(lefwFile,
                 (char*) "            RECT %.11g %.11g %.11g %.11g ",
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile,
                "            RECT MASK %d ITERATE %.11g %.11g %.11g %.11g ",
                mask,
                xl1,
                yl1,
                xl2,
                yl2);
      } else {
        fprintf(lefwFile,
                "            RECT ITERATE %.11g %.11g %.11g %.11g ",
                xl1,
                yl1,
                xl2,
                yl2);
      }
      fprintf(lefwFile,
              "DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile,
                "            RECT MASK %d %.11g %.11g %.11g %.11g ",
                mask,
                xl1,
                yl1,
                xl2,
                yl2);
      } else {
        fprintf(lefwFile,
                "            RECT %.11g %.11g %.11g %.11g ",
                xl1,
                yl1,
                xl2,
                yl2);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroPinPortLayerPolygon(int num_polys,
                                 double* xl,
                                 double* yl,
                                 int numX,
                                 int numY,  // optional
                                 double spaceX,
                                 double spaceY,  // optional
                                 int mask)
{  // optional
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPortLayer) {
    return LEFW_BAD_ORDER;
  }
  if (num_polys < 4) {
    return LEFW_BAD_DATA;  // at least 4 points
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(
            lefwFile, (char*) "            POLYGON MASK %d ITERATE ", mask);
      } else {
        encPrint(lefwFile, (char*) "            POLYGON ITERATE ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g\n", *xl++, *yl++);
        } else {
          encPrint(
              lefwFile, (char*) "               %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      encPrint(lefwFile,
               (char*) "               DO %d BY %d STEP %.11g %.11g ;\n",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile, (char*) "            POLYGON MASK %d ", mask);
      } else {
        encPrint(lefwFile, (char*) "            POLYGON ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g", *xl++, *yl++);
        } else {
          encPrint(
              lefwFile, (char*) "\n               %.11g %.11g", *xl++, *yl++);
        }
        lefwLines++;
      }
      encPrint(lefwFile, (char*) " ;\n");
    }
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile, "            POLYGON MASK %d ITERATE ", mask);
      } else {
        fprintf(lefwFile, "            POLYGON ITERATE ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g\n", *xl++, *yl++);
        } else {
          fprintf(lefwFile, "               %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      fprintf(lefwFile,
              "               DO %d BY %d STEP %.11g %.11g ;\n",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile, "            POLYGON MASK %d ", mask);
      } else {
        fprintf(lefwFile, "            POLYGON ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g", *xl++, *yl++);
        } else {
          fprintf(lefwFile, "\n               %.11g %.11g", *xl++, *yl++);
        }
        lefwLines++;
      }
      fprintf(lefwFile, " ;\n");
    }
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroPinPortVia(double xl,
                        double yl,
                        const char* viaName,
                        int numX,
                        int numY,  // optional
                        double spaceX,
                        double spaceY,  // optional
                        int mask)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroPinPort) {
    return LEFW_BAD_ORDER;
  }
  if (!viaName || viaName == nullptr || *viaName == 0) {
    return LEFW_BAD_DATA;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(lefwFile,
                 (char*) "            VIA ITERATE MASK %d %.11g %.11g %s ",
                 mask,
                 xl,
                 yl,
                 viaName);
      } else {
        encPrint(lefwFile,
                 (char*) "            VIA ITERATE %.11g %.11g %s ",
                 xl,
                 yl,
                 viaName);
      }
      encPrint(lefwFile,
               (char*) "DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      encPrint(
          lefwFile, (char*) "            VIA %.11g %.11g %s ", xl, yl, viaName);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile,
                "            VIA ITERATE MASK %d %.11g %.11g %s ",
                mask,
                xl,
                yl,
                viaName);
      } else {
        fprintf(lefwFile,
                "            VIA ITERATE %.11g %.11g %s ",
                xl,
                yl,
                viaName);
      }
      fprintf(lefwFile,
              "DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile,
                "            VIA MASK %d %.11g %.11g %s ",
                mask,
                xl,
                yl,
                viaName);
      } else {
        fprintf(lefwFile, "            VIA %.11g %.11g %s ", xl, yl, viaName);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwEndMacroPinPort()
{
  if (!lefwIsMacroPinPort) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      END\n");
  } else {
    fprintf(lefwFile, "      END\n");
  }

  lefwLines++;
  lefwIsMacroPinPort = 0;
  return LEFW_OK;
}

int lefwStartMacroObs()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   OBS\n");
  } else {
    fprintf(lefwFile, "   OBS\n");
  }

  lefwIsMacroObs = 1;
  lefwSpacingVal = 0;
  lefwWidthVal = 0;
  lefwLines++;
  return LEFW_OK;
}

int lefwMacroObsLayer(const char* layerName, double spacing)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWidthVal) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      LAYER %s ", layerName);
    if (spacing) {
      encPrint(lefwFile, (char*) "SPACING %.11g ", spacing);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      LAYER %s ", layerName);
    if (spacing) {
      fprintf(lefwFile, "SPACING %.11g ", spacing);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwIsMacroObsLayer = 1;
  lefwSpacingVal = 1;
  return LEFW_OK;
}

int lefwMacroObsDesignRuleWidth(const char* layerName, double width)
{
  lefw54Num = LEFW_DESIGNRULEWIDTH;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwSpacingVal) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      LAYER %s ", layerName);
    if (width) {
      encPrint(lefwFile, (char*) "DESIGNRULEWIDTH %.11g ", width);
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    fprintf(lefwFile, "      LAYER %s ", layerName);
    if (width) {
      fprintf(lefwFile, "DESIGNRULEWIDTH %.11g ", width);
    }
    fprintf(lefwFile, ";\n");
  }
  lefwLines++;
  lefwIsMacroObsLayer = 1;
  lefwWidthVal = 1;
  return LEFW_OK;
}

int lefwMacroExceptPGNet(const char* layerName)
{
  lefw54Num = LEFW_DESIGNRULEWIDTH;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (!layerName || layerName == nullptr || *layerName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwSpacingVal) {
    return LEFW_BAD_DATA;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      LAYER %s EXCEPTPGNET ;\n", layerName);
  } else {
    fprintf(lefwFile, "      LAYER %s EXCEPTPGNET ;\n", layerName);
  }
  lefwLines++;
  lefwIsMacroObsLayer = 1;
  lefwWidthVal = 1;
  return LEFW_OK;
}

int lefwMacroObsLayerWidth(double width)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObsLayer) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      WIDTH %.11g ;\n", width);
  } else {
    fprintf(lefwFile, "      WIDTH %.11g ;\n", width);
  }
  lefwLines++;
  lefwIsMacroObsLayer = 1;
  return LEFW_OK;
}

int lefwMacroObsLayerPath(int num_paths,
                          double* xl,
                          double* yl,
                          int numX,
                          int numY,  // optional
                          double spaceX,
                          double spaceY,  // optional
                          int mask)
{  // optional
  int i, numItem;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObsLayer) {
    return LEFW_BAD_ORDER;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(lefwFile, (char*) "         PATH MASK %d ITERATE ", mask);
      } else {
        encPrint(lefwFile, (char*) "         PATH ITERATE ");
      }
      for (i = 0; i < num_paths; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g\n", *xl++, *yl++);
        } else {
          encPrint(lefwFile, (char*) "            %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      encPrint(lefwFile,
               (char*) "           DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile, (char*) "         PATH MASK %d ", mask);
      } else {
        encPrint(lefwFile, (char*) "         PATH ");
      }
      numItem = 0;
      for (i = 0; i < num_paths; i++) {
        if (numItem > 5) {
          encPrint(lefwFile, (char*) "\n");
          encPrint(lefwFile, (char*) "         %.11g %.11g ", xl[i], yl[i]);
          numItem = 0;
          lefwLines++;
        } else {
          encPrint(lefwFile, (char*) "%.11g %.11g ", xl[i], yl[i]);
        }
        numItem++;
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile, "         PATH MASK %d ITERATE ", mask);
      } else {
        fprintf(lefwFile, "         PATH ITERATE ");
      }
      for (i = 0; i < num_paths; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g\n", *xl++, *yl++);
        } else {
          fprintf(lefwFile, "            %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      fprintf(lefwFile,
              "           DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile, "         PATH MASK %d ", mask);
      } else {
        fprintf(lefwFile, "         PATH ");
      }
      numItem = 0;
      for (i = 0; i < num_paths; i++) {
        if (numItem > 5) {
          fprintf(lefwFile, "\n");
          fprintf(lefwFile, "         %.11g %.11g ", xl[i], yl[i]);
          numItem = 0;
          lefwLines++;
        } else {
          fprintf(lefwFile, "%.11g %.11g ", xl[i], yl[i]);
        }
        numItem++;
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroObsLayerRect(double xl1,
                          double yl1,
                          double xl2,
                          double yl2,
                          int numX,
                          int numY,  // optional
                          double spaceX,
                          double spaceY,  // optional
                          int mask)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObsLayer) {
    return LEFW_BAD_ORDER;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(
            lefwFile,
            (char*) "         RECT MASK %d ITERATE %.11g %.11g %.11g %.11g ",
            mask,
            xl1,
            yl1,
            xl2,
            yl2);
      } else {
        encPrint(lefwFile,
                 (char*) "         RECT ITERATE %.11g %.11g %.11g %.11g ",
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      }
      encPrint(lefwFile,
               (char*) "DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile,
                 (char*) "         RECT MASK %d %.11g %.11g %.11g %.11g ",
                 mask,
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      } else {
        encPrint(lefwFile,
                 (char*) "         RECT %.11g %.11g %.11g %.11g ",
                 xl1,
                 yl1,
                 xl2,
                 yl2);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile,
                "         RECT MASK %d ITERATE %.11g %.11g %.11g %.11g ",
                mask,
                xl1,
                yl1,
                xl2,
                yl2);
      } else {
        fprintf(lefwFile,
                "         RECT ITERATE %.11g %.11g %.11g %.11g ",
                xl1,
                yl1,
                xl2,
                yl2);
      }
      fprintf(lefwFile,
              "DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile,
                "         RECT MASK %d %.11g %.11g %.11g %.11g ",
                mask,
                xl1,
                yl1,
                xl2,
                yl2);
      } else {
        fprintf(lefwFile,
                "         RECT %.11g %.11g %.11g %.11g ",
                xl1,
                yl1,
                xl2,
                yl2);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroObsLayerPolygon(int num_polys,
                             double* xl,
                             double* yl,
                             int numX,
                             int numY,  // optional
                             double spaceX,
                             double spaceY,  // optional
                             int mask)
{  // optional
  int i;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObsLayer) {
    return LEFW_BAD_ORDER;
  }
  if (num_polys < 4) {
    return LEFW_BAD_DATA;  // at least 4 points
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(lefwFile, (char*) "         POLYGON MASK %d ITERATE ", mask);
      } else {
        encPrint(lefwFile, (char*) "         POLYGON ITERATE ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g\n", *xl++, *yl++);
        } else {
          encPrint(lefwFile, (char*) "           %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      encPrint(lefwFile,
               (char*) "           DO %d BY %d STEP %.11g %.11g ;",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile, (char*) "         POLYGON MASK %d ", mask);
      } else {
        encPrint(lefwFile, (char*) "         POLYGON ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          encPrint(lefwFile, (char*) "%.11g %.11g", *xl++, *yl++);
        } else {
          encPrint(lefwFile, (char*) "\n           %.11g %.11g", *xl++, *yl++);
        }
        lefwLines++;
      }
      encPrint(lefwFile, (char*) " ;\n");
    }
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile, "         POLYGON MASK %d ITERATE ", mask);
      } else {
        fprintf(lefwFile, "         POLYGON ITERATE ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g\n", *xl++, *yl++);
        } else {
          fprintf(lefwFile, "           %.11g %.11g\n", *xl++, *yl++);
        }
        lefwLines++;
      }
      fprintf(lefwFile,
              "           DO %d BY %d STEP %.11g %.11g ;",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile, "         POLYGON MASK %d ", mask);
      } else {
        fprintf(lefwFile, "         POLYGON ");
      }
      for (i = 0; i < num_polys; i++) {
        if (i == 0) {
          fprintf(lefwFile, "%.11g %.11g", *xl++, *yl++);
        } else {
          fprintf(lefwFile, "\n           %.11g %.11g", *xl++, *yl++);
        }
        lefwLines++;
      }
      fprintf(lefwFile, " ;\n");
    }
  }

  lefwLines++;
  return LEFW_OK;
}

int lefwMacroObsVia(double xl,
                    double yl,
                    const char* viaName,
                    int numX,
                    int numY,  // optional
                    double spaceX,
                    double spaceY,  // optional
                    int mask)
{  // optional
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (!viaName || viaName == nullptr || *viaName == 0) {
    return LEFW_BAD_DATA;
  }
  if (mask && versionNum < 5.8) {
    return LEFW_WRONG_VERSION;
  }

  if (!lefwValidateMaskNumber(mask)) {
    return LEFW_BAD_DATA;
  }

  if (lefwWriteEncrypt) {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        encPrint(lefwFile,
                 (char*) "      VIA ITERATE MASK %d %.11g %.11g %s ",
                 mask,
                 xl,
                 yl,
                 viaName);
      } else {
        encPrint(lefwFile,
                 (char*) "      VIA ITERATE %.11g %.11g %s ",
                 xl,
                 yl,
                 viaName);
      }
      encPrint(lefwFile,
               (char*) "DO %d BY %d STEP %.11g %.11g ",
               numX,
               numY,
               spaceX,
               spaceY);
    } else {
      if (mask) {
        encPrint(lefwFile,
                 (char*) "      VIA MASK %d %.11g %.11g %s ",
                 mask,
                 xl,
                 yl,
                 viaName);
      } else {
        encPrint(
            lefwFile, (char*) "      VIA %.11g %.11g %s ", xl, yl, viaName);
      }
    }
    encPrint(lefwFile, (char*) ";\n");
  } else {
    if (numX || numY || spaceX || spaceY) {
      if (mask) {
        fprintf(lefwFile,
                "      VIA ITERATE MASK %d %.11g %.11g %s ",
                mask,
                xl,
                yl,
                viaName);
      } else {
        fprintf(lefwFile, "      VIA ITERATE %.11g %.11g %s ", xl, yl, viaName);
      }
      fprintf(lefwFile,
              "DO %d BY %d STEP %.11g %.11g ",
              numX,
              numY,
              spaceX,
              spaceY);
    } else {
      if (mask) {
        fprintf(lefwFile,
                "      VIA MASK %d %.11g %.11g %s ",
                mask,
                xl,
                yl,
                viaName);
      } else {
        fprintf(lefwFile, "      VIA %.11g %.11g %s ", xl, yl, viaName);
      }
    }
    fprintf(lefwFile, ";\n");
  }

  lefwLines++;
  lefwIsMacroObsLayer = 0;
  return LEFW_OK;
}

int lefwEndMacroObs()
{
  if (!lefwIsMacroObs) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END\n");
  } else {
    fprintf(lefwFile, "   END\n");
  }

  lefwLines++;
  lefwIsMacroObs = 0;
  return LEFW_OK;
}

int lefwStartMacroTiming()
{
  lefwObsoleteNum = LEFW_MACRO_TIMING;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_MACRO_START && lefwState != LEFW_MACRO) {
    return LEFW_BAD_ORDER;
  }
  if (lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (versionNum >= 5.4) {
    return LEFW_OBSOLETE;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   TIMING\n");
  } else {
    fprintf(lefwFile, "   TIMING\n");
  }

  lefwIsMacroTiming = 1;
  lefwIsMacroTimingModel = 0;
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingPin(const char* fromPin, const char* toPin)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (fromPin) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "      FROMPIN %s ;\n", fromPin);
    } else {
      fprintf(lefwFile, "      FROMPIN %s ;\n", fromPin);
    }
    lefwLines++;
  }
  if (toPin) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "      TOPIN %s ;\n", toPin);
    } else {
      fprintf(lefwFile, "      TOPIN %s ;\n", toPin);
    }
    lefwLines++;
  }
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingIntrinsic(const char* riseFall,
                             double min,
                             double max,
                             double slewT1,
                             double slewT1Min,  // optional
                             double slewT1Max,
                             double slewT2,  // optional
                             double slewT2Min,
                             double slewT2Max,  // optional
                             double slewT3,     // optional
                             double varMin,
                             double varMax)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (strcmp(riseFall, "RISE") && strcmp(riseFall, "FALL")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile,
             (char*) "      %s INTRINSIC %.11g %.11g ",
             riseFall,
             min,
             max);
    if (slewT1 || slewT1Min || slewT1Max || slewT2) {
      encPrint(lefwFile,
               (char*) "%.11g %.11g %.11g %.11g ",
               slewT1,
               slewT1Min,
               slewT1Max,
               slewT2);
      if (slewT2Min || slewT2Max || slewT3) {
        encPrint(lefwFile,
                 (char*) "%.11g %.11g %.11g \n",
                 slewT2Min,
                 slewT2Max,
                 slewT3);
      }
    } else if (slewT2Min || slewT2Max || slewT3) {
      return LEFW_BAD_DATA;  // slewT2Min... has to be inside of slewT1...
    }
    encPrint(
        lefwFile, (char*) "         VARIABLE %.11g %.11g ;\n", varMin, varMax);
  } else {
    fprintf(lefwFile, "      %s INTRINSIC %.11g %.11g ", riseFall, min, max);
    if (slewT1 || slewT1Min || slewT1Max || slewT2) {
      fprintf(lefwFile,
              "%.11g %.11g %.11g %.11g ",
              slewT1,
              slewT1Min,
              slewT1Max,
              slewT2);
      if (slewT2Min || slewT2Max || slewT3) {
        fprintf(lefwFile, "%.11g %.11g %.11g \n", slewT2Min, slewT2Max, slewT3);
      }
    } else if (slewT2Min || slewT2Max || slewT3) {
      return LEFW_BAD_DATA;  // slewT2Min... has to be inside of slewT1...
    }
    fprintf(lefwFile, "         VARIABLE %.11g %.11g ;\n", varMin, varMax);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingRisers(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISERS %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      RISERS %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingFallrs(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLRS %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      FALLRS %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingRisecs(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISECS %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      RISECS %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingFallcs(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLCS %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      FALLCS %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingRisesatt1(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISESATT1 %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      RISESATT1 %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingFallsatt1(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLSATT1 %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      FALLSATT1 %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingRiset0(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      RISET0 %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      RISET0 %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingFallt0(double min, double max)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      FALLT0 %.11g %.11g ;\n", min, max);
  } else {
    fprintf(lefwFile, "      FALLT0 %.11g %.11g ;\n", min, max);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwMacroTimingUnateness(const char* unateness)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (strcmp(unateness, "INVERT") && strcmp(unateness, "NONINVERT")
      && strcmp(unateness, "NONUNATE")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "      UNATENESS %s ; \n", unateness);
  } else {
    fprintf(lefwFile, "      UNATENESS %s ; \n", unateness);
  }
  lefwLines++;
  return LEFW_OK;
}

// Obsolete in 5.4
int lefwEndMacroTiming()
{
  if (!lefwIsMacroTiming) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   END TIMING\n\n");
  } else {
    fprintf(lefwFile, "   END TIMING\n\n");
  }

  lefwLines++;
  lefwIsMacroTiming = 0;
  return LEFW_OK;
}

int lefwAntenna(const char* type, double value)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (!type || type == nullptr || *type == 0) {
    return LEFW_BAD_DATA;
  }
  if (strcmp(type, "INPUTPINANTENNASIZE")
      && strcmp(type, "OUTPUTPINANTENNASIZE")
      && strcmp(type, "INOUTPINANTENNASIZE")) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "%s %.11g ;\n", type, value);
  } else {
    fprintf(lefwFile, "%s %.11g ;\n", type, value);
  }

  lefwLines++;
  lefwSynArray[LEFW_ANTENNASIZE] = 1;
  return LEFW_OK;
}

int lefwAntennaInputGateArea(double inputGateArea)
{
  lefw54Num = LEFW_ANTENNAINPUTGATEAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_ANTENNAINPUTGATEAREA]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "ANTENNAINPUTGATEAREA %.11g ;\n", inputGateArea);
  } else {
    fprintf(lefwFile, "ANTENNAINPUTGATEAREA %.11g ;\n", inputGateArea);
  }
  lefwLines++;
  lefwSynArray[LEFW_ANTENNAINPUTGATEAREA] = 1;
  return LEFW_OK;
}

int lefwAntennaInOutDiffArea(double inOutDiffArea)
{
  lefw54Num = LEFW_ANTENNAINOUTDIFFAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_ANTENNAINOUTDIFFAREA]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "ANTENNAINOUTDIFFAREA %.11g ;\n", inOutDiffArea);
  } else {
    fprintf(lefwFile, "ANTENNAINOUTDIFFAREA %.11g ;\n", inOutDiffArea);
  }
  lefwLines++;
  lefwSynArray[LEFW_ANTENNAINOUTDIFFAREA] = 1;
  return LEFW_OK;
}

int lefwAntennaOutputDiffArea(double outputDiffArea)
{
  lefw54Num = LEFW_ANTENNAOUTPUTDIFFAREA;
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_INIT && lefwState < LEFW_END) {
    return LEFW_BAD_ORDER;  // not of the ENDs
  }
  if (lefwSynArray[LEFW_ANTENNAOUTPUTDIFFAREA]) {
    return LEFW_ALREADY_DEFINED;
  }
  if (versionNum < 5.4) {
    return LEFW_WRONG_VERSION;
  }
  if (lefwWriteEncrypt) {
    encPrint(
        lefwFile, (char*) "ANTENNAOUTPUTDIFFAREA %.11g ;\n", outputDiffArea);
  } else {
    fprintf(lefwFile, "ANTENNAOUTPUTDIFFAREA %.11g ;\n", outputDiffArea);
  }
  lefwLines++;
  lefwSynArray[LEFW_ANTENNAOUTPUTDIFFAREA] = 1;
  return LEFW_OK;
}

int lefwStartBeginext(const char* name)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState == LEFW_BEGINEXT_START || lefwState == LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }
  if (!name || name == nullptr || *name == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "BEGINEXT \"%s\"", name);
  }
  // \n will be added later
  else {
    fprintf(lefwFile, "BEGINEXT \"%s\"", name);
  }

  lefwState = LEFW_BEGINEXT_START;
  lefwLines++;
  return LEFW_OK;
}

int lefwBeginextCreator(const char* creatorName)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_BEGINEXT_START && lefwState != LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }
  if (!creatorName || creatorName == nullptr || *creatorName == 0) {
    return LEFW_BAD_DATA;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n   CREATOR \"%s\"", creatorName);
  } else {
    fprintf(lefwFile, "\n   CREATOR \"%s\"", creatorName);
  }

  lefwState = LEFW_BEGINEXT;
  lefwLines++;
  return LEFW_OK;
}

int lefwBeginextDate()
{
  time_t todayTime;
  char* rettime;

  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_BEGINEXT_START && lefwState != LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }

  todayTime = time(nullptr);            // time in UTC
  rettime = ctime(&todayTime);          // convert to string
  rettime[strlen(rettime) - 1] = '\0';  // replace \n with \0
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n   DATE \"%s\"", rettime);
  } else {
    fprintf(lefwFile, "\n   DATE \"%s\"", rettime);
  }

  lefwState = LEFW_BEGINEXT;
  lefwLines++;
  return LEFW_OK;
}

int lefwBeginextRevision(int vers1, int vers2)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_BEGINEXT_START && lefwState != LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n   REVISION %d.%d", vers1, vers2);
  } else {
    fprintf(lefwFile, "\n   REVISION %d.%d", vers1, vers2);
  }

  lefwState = LEFW_BEGINEXT;
  lefwLines++;
  return LEFW_OK;
}

int lefwBeginextSyntax(const char* title, const char* string)
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_BEGINEXT_START && lefwState != LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "\n   - %s %s", title, string);
  } else {
    fprintf(lefwFile, "\n   - %s %s", title, string);
  }

  lefwState = LEFW_BEGINEXT;
  lefwLines++;
  return LEFW_OK;
}

int lefwEndBeginext()
{
  if (!lefwFile) {
    return LEFW_UNINITIALIZED;
  }
  if (!lefwDidInit) {
    return LEFW_BAD_ORDER;
  }
  if (lefwState != LEFW_BEGINEXT_START && lefwState != LEFW_BEGINEXT) {
    return LEFW_BAD_ORDER;
  }
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) ";\nENDEXT\n\n");
  } else {
    fprintf(lefwFile, ";\nENDEXT\n\n");
  }

  lefwState = LEFW_BEGINEXT_END;
  lefwLines++;
  return LEFW_OK;
}

int lefwCurrentLineNumber()
{
  return lefwLines;
}

void lefwPrintError(int status)
{
  switch (status) {
    case LEFW_OK:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "No Error.\n");
      } else {
        fprintf(lefwFile, "No Error.\n");
      }
      break;
    case LEFW_UNINITIALIZED:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "Need to call lefwInit first.\n");
      } else {
        fprintf(lefwFile, "Need to call lefwInit first.\n");
      }
      break;
    case LEFW_BAD_ORDER:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "Incorrect order of data.\n");
      } else {
        fprintf(lefwFile, "Incorrect order of data.\n");
      }
      break;
    case LEFW_BAD_DATA:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "Invalid data.\n");
      } else {
        fprintf(lefwFile, "Invalid data.\n");
      }
      break;
    case LEFW_ALREADY_DEFINED:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "Section is allowed to define only once.\n");
      } else {
        fprintf(lefwFile, "Section is allowed to define only once.\n");
      }
      break;
    case LEFW_WRONG_VERSION:
      if (lefwWriteEncrypt) {
        encPrint(
            lefwFile,
            (char*) "Version number is set before 5.4, API: %s is for 5.4.\n",
            lefwStateStr[lefw54Num]);
      } else {
        fprintf(
            lefwFile,
            "Version number is set before 5.4, but 5.4, API: %s is for 5.4.\n",
            lefwStateStr[lefw54Num]);
      }
      break;
    case LEFW_MIX_VERSION_DATA:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile, (char*) "You have made both 5.4 & pre 5.4 Antenna API called, which is invalid.\n");
      }

      else {
        fprintf(lefwFile,
                "You have made both 5.4 & pre 5.4 Antenna API called, which is "
                "invalid.\n");
      }
      break;
    case LEFW_OBSOLETE:
      if (lefwWriteEncrypt) {
        encPrint(lefwFile,
                 (char*) "%s is no longer valid in %g.\n",
                 lefwStateStr[lefwObsoleteNum],
                 versionNum);
      }

      else {
        fprintf(lefwFile,
                "%s is no longer valid in %g.\n",
                lefwStateStr[lefwObsoleteNum],
                versionNum);
      }
  }
  return;
}

void lefwAddComment(const char* comment)
{
  if (comment) {
    if (lefwWriteEncrypt) {
      encPrint(lefwFile, (char*) "# %s\n", comment);
    } else {
      fprintf(lefwFile, "# %s\n", comment);
    }
  }
  return;
}

void lefwAddIndent()
{
  if (lefwWriteEncrypt) {
    encPrint(lefwFile, (char*) "   ");
  } else {
    fprintf(lefwFile, "   ");
  }
  return;
}

// ***************************
//   Questions:
// - Is only one row rule allowed
// - Is only one tracks rule allowed
// - In the die area is a zero area allowed? overlaps?
// - What type of checking is needed for the rows and tracks do loop?
// - Can you have a default prop with a number AND a range?
// - What is the pin properties section mentioned in the 5.1 spec?
// *****************************

END_LEF_PARSER_NAMESPACE
